Only resort if we actually get new data from the server. (#915)

* Only resort if we actually get new data from the server.

* Further reduction in CPU usage by having highlights clear on a slightly longer time interval.

* Further CPU reductions by only re-sorting if data's actually changed.

* Further filter by current sorting column.

* Oops, sorting column should be the same as the modified column to trigger sorting.

* Fix crash when exiting FreeDV.

* Check IsValid() to avoid assertion on wxWidgets 3.0.

* Fix other wxWidgets 3.0 assertions discovered during testing.

* Reduce CPU load used by rendering frequency updates by only sending updates to the server when the frequency changes.

* Add PR #915 to changelog.
ms-gtk-assert-fix
Mooneer Salem 2025-06-10 08:54:20 -07:00 committed by GitHub
parent 405134f49c
commit 03a4d87970
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 14 deletions

View File

@ -800,6 +800,7 @@ LDPC | Low Density Parity Check Codes - a family of powerful FEC codes
* Unit tests: Increase sleep time before killing recording to resolve macOS test failures. (PR #917)
* Fix typo causing RX radio device to remain open. (PR #918)
* Fix WASAPI errors on some machines by supporting audio mix formats other than 16-bit integer. (PR #919)
* Reduce CPU usage of FreeDV Reporter window by only re-sorting if we actually get new data from the server. (PR #915)
* FreeDV Reporter: Fix issue with first column not being aligned properly with other columns. (PR #922)
2. Documentation:
* Add missing dependency for macOS builds to README. (PR #925; thanks @relistan!)

View File

@ -337,10 +337,13 @@ FreeDVReporterDialog::FreeDVReporterDialog(wxWindow* parent, wxWindowID id, cons
wxGetApp().appConfiguration.reporterWindowTop = actualPos.y;
SetPosition(actualPos);
// Set up highlight clear timer
// Set up timers. Highlight clear timer has a slightly longer interval
// to reduce CPU usage.
m_highlightClearTimer = new wxTimer(this);
m_highlightClearTimer->Start(100);
m_highlightClearTimer->Start(250);
m_resortTimer = new wxTimer(this);
m_resortTimer->Start(100);
// Create Set popup menu
setPopupMenu_ = new wxMenu();
assert(setPopupMenu_ != nullptr);
@ -447,6 +450,9 @@ FreeDVReporterDialog::~FreeDVReporterDialog()
{
m_highlightClearTimer->Stop();
delete m_highlightClearTimer;
m_resortTimer->Stop();
delete m_resortTimer;
m_trackFrequency->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this);
m_trackFreqBand->Disconnect(wxEVT_RADIOBUTTON, wxCommandEventHandler(FreeDVReporterDialog::OnFilterTrackingEnable), NULL, this);
@ -789,8 +795,18 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::updateHighlights()
void FreeDVReporterDialog::OnTimer(wxTimerEvent& event)
{
FreeDVReporterDataModel* model = (FreeDVReporterDataModel*)spotsDataModel_.get();
model->updateHighlights();
model->Resort();
if (event.GetTimer().GetId() == m_highlightClearTimer->GetId())
{
model->updateHighlights();
}
else
{
if (model->sortOnNextTimerInterval)
{
model->Resort();
model->sortOnNextTimerInterval = false;
}
}
}
void FreeDVReporterDialog::OnFilterTrackingEnable(wxCommandEvent& event)
@ -1407,7 +1423,8 @@ wxString FreeDVReporterDialog::FreeDVReporterDataModel::GetCardinalDirection_(in
}
FreeDVReporterDialog::FreeDVReporterDataModel::FreeDVReporterDataModel(FreeDVReporterDialog* parent)
: isConnected_(false)
: sortOnNextTimerInterval(false)
, isConnected_(false)
, parent_(parent)
, currentBandFilter_(FreeDVReporterDialog::BAND_ALL)
, filterSelfMessageUpdates_(false)
@ -1861,6 +1878,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::refreshAllRows()
{
ItemDeleted(wxDataViewItem(nullptr), wxDataViewItem(kvp.second));
}
sortOnNextTimerInterval = true;
}
else if (updated && kvp.second->isVisible)
{
@ -2029,6 +2047,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onUserConnectFn_(std::string
if (temp->isVisible)
{
ItemAdded(wxDataViewItem(nullptr), wxDataViewItem(temp));
sortOnNextTimerInterval = true;
}
});
@ -2101,6 +2120,11 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onFrequencyChangeFn_(std::st
frequencyString = wxString::Format(_("%.04f"), frequencyUserReadable);
}
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
bool isChanged =
(sortingColumn == parent_->m_listSpots->GetColumn(FREQUENCY_COL) && iter->second->frequency != frequencyHz) ||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->frequency = frequencyHz;
iter->second->freqString = frequencyString;
@ -2119,10 +2143,12 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onFrequencyChangeFn_(std::st
{
ItemDeleted(wxDataViewItem(nullptr), dvi);
}
sortOnNextTimerInterval = true;
}
else if (newVisibility)
{
ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
}
}
});
@ -2139,8 +2165,10 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onTransmitUpdateFn_(std::str
auto iter = allReporterData_.find(sid);
if (iter != allReporterData_.end())
{
bool isChanged = iter->second->transmitting != transmitting;
iter->second->transmitting = transmitting;
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
std::string txStatus = "RX";
if (transmitting)
{
@ -2149,20 +2177,27 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onTransmitUpdateFn_(std::str
if (iter->second->status != _(RX_ONLY_STATUS))
{
isChanged |=
(sortingColumn == parent_->m_listSpots->GetColumn(STATUS_COL) && iter->second->status != txStatus) ||
(sortingColumn == parent_->m_listSpots->GetColumn(TX_MODE_COL) && iter->second->txMode != txMode);
iter->second->status = txStatus;
iter->second->txMode = txMode;
auto lastTxTime = makeValidTime_(lastTxDate, iter->second->lastTxDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_TX_DATE_COL) && iter->second->lastTx != lastTxTime);
iter->second->lastTx = lastTxTime;
}
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->lastUpdate = lastUpdateTime;
if (iter->second->isVisible)
{
wxDataViewItem dvi(iter->second);
ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
}
}
});
@ -2178,17 +2213,29 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
auto iter = allReporterData_.find(sid);
if (iter != allReporterData_.end())
{
{
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
bool isChanged =
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != receivedCallsign) ||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_MODE_COL) && iter->second->lastRxMode != rxMode);
iter->second->lastRxCallsign = receivedCallsign;
iter->second->lastRxMode = rxMode;
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->lastUpdate = lastUpdateTime;
wxString snrString = wxString::Format(_("%.01f"), snr);
if (receivedCallsign == "" && rxMode == "")
{
// Frequency change--blank out SNR too.
isChanged |=
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_CALLSIGN_COL) && iter->second->lastRxCallsign != UNKNOWN_STR) ||
(sortingColumn == parent_->m_listSpots->GetColumn(LAST_RX_MODE_COL) && iter->second->lastRxMode != UNKNOWN_STR) ||
(sortingColumn == parent_->m_listSpots->GetColumn(SNR_COL) && iter->second->snr != UNKNOWN_STR) ||
iter->second->lastRxDate.IsValid();
iter->second->lastRxCallsign = UNKNOWN_STR;
iter->second->lastRxMode = UNKNOWN_STR;
iter->second->snr = UNKNOWN_STR;
@ -2196,6 +2243,8 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
}
else
{
isChanged |=
(sortingColumn == parent_->m_listSpots->GetColumn(SNR_COL) && iter->second->snr != snrString);
iter->second->snr = snrString;
iter->second->lastRxDate = wxDateTime::Now();
}
@ -2204,6 +2253,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onReceiveUpdateFn_(std::stri
{
wxDataViewItem dvi(iter->second);
ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
}
}
});
@ -2219,17 +2269,22 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onMessageUpdateFn_(std::stri
auto iter = allReporterData_.find(sid);
if (iter != allReporterData_.end())
{
{
auto sortingColumn = parent_->m_listSpots->GetSortingColumn();
bool isChanged = false;
if (message.size() == 0)
{
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(USER_MESSAGE_COL) && iter->second->userMessage != UNKNOWN_STR);
iter->second->userMessage = UNKNOWN_STR;
}
else
{
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(USER_MESSAGE_COL) && iter->second->userMessage != wxString::FromUTF8(message.c_str()));
iter->second->userMessage = wxString::FromUTF8(message.c_str());
}
auto lastUpdateTime = makeValidTime_(lastUpdate, iter->second->lastUpdateDate);
isChanged |= (sortingColumn == parent_->m_listSpots->GetColumn(LAST_UPDATE_DATE_COL) && iter->second->lastUpdate != lastUpdateTime);
iter->second->lastUpdate = lastUpdateTime;
// Only highlight on non-empty messages.
@ -2250,6 +2305,7 @@ void FreeDVReporterDialog::FreeDVReporterDataModel::onMessageUpdateFn_(std::stri
{
wxDataViewItem dvi(iter->second);
ItemChanged(dvi);
sortOnNextTimerInterval |= isChanged;
}
}
});

View File

@ -141,6 +141,7 @@ class FreeDVReporterDialog : public wxFrame
wxButton* m_buttonDisplayWebpage;
// Timer to unhighlight RX rows after 10s (like with web-based Reporter)
wxTimer* m_resortTimer;
wxTimer* m_highlightClearTimer;
wxTipWindow* tipWindow_;
@ -217,6 +218,8 @@ class FreeDVReporterDialog : public wxFrame
virtual wxString GetColumnType (unsigned int col) const override;
#endif // !wxCHECK_VERSION(3,2,0)
bool sortOnNextTimerInterval;
private:
struct ReporterData
{

View File

@ -1237,15 +1237,15 @@ void MainFrame::OnChangeReportFrequency( wxCommandEvent& event )
wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency = 0;
m_cboReportFrequency->SetForegroundColour(wxColor(*wxRED));
}
// Report current frequency to reporters
for (auto& ptr : wxGetApp().m_reporters)
{
ptr->freqChange(wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency);
}
if (oldFreq != wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency)
{
// Report current frequency to reporters
for (auto& ptr : wxGetApp().m_reporters)
{
ptr->freqChange(wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency);
}
if (wxGetApp().rigFrequencyController != nullptr &&
wxGetApp().appConfiguration.reportingConfiguration.reportingFrequency > 0 &&
(wxGetApp().appConfiguration.rigControlConfiguration.hamlibEnableFreqModeChanges || wxGetApp().appConfiguration.rigControlConfiguration.hamlibEnableFreqChangesOnly))