From dc88eb65fb71a2b6a058aaec3dd49cba443e5f21 Mon Sep 17 00:00:00 2001 From: Jacob Walser Date: Tue, 16 Jan 2018 11:42:10 -0500 Subject: [PATCH 01/11] Correct video file timestamping issues --- src/VideoStreaming/VideoReceiver.cc | 35 +++++++++++++++++++++++++++++++++++ src/VideoStreaming/VideoReceiver.h | 1 + 2 files changed, 36 insertions(+) diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc index 7f46d85..e563dcf 100644 --- a/src/VideoStreaming/VideoReceiver.cc +++ b/src/VideoStreaming/VideoReceiver.cc @@ -674,6 +674,14 @@ VideoReceiver::startRecording(const QString &videoFile) gst_element_sync_state_with_parent(_sink->mux); gst_element_sync_state_with_parent(_sink->filesink); + // Install a probe on the recording branch to drop buffers until we hit our first keyframe + // When we hit our first keyframe, we can offset the timestamps appropriately according to the first keyframe time + // This will ensure the first frame is a keyframe at t=0, and decoding can begin immediately on playback + GstPad* probepad = gst_element_get_static_pad(_sink->queue, "src"); + gst_pad_add_probe(probepad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER /* | GST_PAD_PROBE_TYPE_BLOCK */), _keyframeWatch, this, NULL); // to drop the buffer or to block the buffer? + gst_object_unref(probepad); + + // Link the recording branch to the pipeline GstPad* sinkpad = gst_element_get_static_pad(_sink->queue, "sink"); gst_pad_link(_sink->teepad, sinkpad); gst_object_unref(sinkpad); @@ -803,6 +811,33 @@ VideoReceiver::_unlinkCallBack(GstPad* pad, GstPadProbeInfo* info, gpointer user #endif //----------------------------------------------------------------------------- +#if defined(QGC_GST_STREAMING) +GstPadProbeReturn +VideoReceiver::_keyframeWatch(GstPad* pad, GstPadProbeInfo* info, gpointer user_data) +{ + Q_UNUSED(pad); + if(info != NULL && user_data != NULL) { + GstBuffer* buf = gst_pad_probe_info_get_buffer(info); + if(GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT)) { // wait for a keyframe + return GST_PAD_PROBE_DROP; + } else { + VideoReceiver* pThis = (VideoReceiver*)user_data; + // reset the clock + GstClock* clock = gst_pipeline_get_pipeline_clock(GST_PIPELINE(pThis->_pipeline)); + GstClockTime time = gst_clock_get_time(clock); + gst_object_unref(clock); + gst_element_set_base_time(pThis->_pipeline, time); // offset pipeline timestamps to start at zero again + buf->dts = 0; // The offset will not apply to this current buffer, our first frame, timestamp is zero + buf->pts = 0; + qCDebug(VideoReceiverLog) << "Got keyframe, stop dropping buffers"; + } + } + + return GST_PAD_PROBE_REMOVE; +} +#endif + +//----------------------------------------------------------------------------- void VideoReceiver::_updateTimer() { diff --git a/src/VideoStreaming/VideoReceiver.h b/src/VideoStreaming/VideoReceiver.h index 843abdf..76aa304 100644 --- a/src/VideoStreaming/VideoReceiver.h +++ b/src/VideoStreaming/VideoReceiver.h @@ -119,6 +119,7 @@ private: static gboolean _onBusMessage (GstBus* bus, GstMessage* message, gpointer user_data); static GstPadProbeReturn _unlinkCallBack (GstPad* pad, GstPadProbeInfo* info, gpointer user_data); + static GstPadProbeReturn _keyframeWatch (GstPad* pad, GstPadProbeInfo* info, gpointer user_data); void _detachRecordingBranch (GstPadProbeInfo* info); void _shutdownRecordingBranch(); void _shutdownPipeline (); From 54cbb2ed9bf8a831af154e6d33eab4404a27e9a8 Mon Sep 17 00:00:00 2001 From: Jacob Walser Date: Wed, 17 Jan 2018 14:33:53 -0500 Subject: [PATCH 02/11] use 1.2.4 api --- src/VideoStreaming/VideoReceiver.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc index e563dcf..633688e 100644 --- a/src/VideoStreaming/VideoReceiver.cc +++ b/src/VideoStreaming/VideoReceiver.cc @@ -823,7 +823,7 @@ VideoReceiver::_keyframeWatch(GstPad* pad, GstPadProbeInfo* info, gpointer user_ } else { VideoReceiver* pThis = (VideoReceiver*)user_data; // reset the clock - GstClock* clock = gst_pipeline_get_pipeline_clock(GST_PIPELINE(pThis->_pipeline)); + GstClock* clock = gst_pipeline_get_clock(GST_PIPELINE(pThis->_pipeline)); GstClockTime time = gst_clock_get_time(clock); gst_object_unref(clock); gst_element_set_base_time(pThis->_pipeline, time); // offset pipeline timestamps to start at zero again From ff44b56a701df287eefdcbbb3a5711034a64d934 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Wed, 4 Apr 2018 09:08:00 -0700 Subject: [PATCH 03/11] Fix crash when image count is less than trigger count --- src/AnalyzeView/GeoTagController.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/AnalyzeView/GeoTagController.cc b/src/AnalyzeView/GeoTagController.cc index 33ee123..2db65e7 100644 --- a/src/AnalyzeView/GeoTagController.cc +++ b/src/AnalyzeView/GeoTagController.cc @@ -259,6 +259,11 @@ void GeoTagWorker::run(void) int maxIndex = std::min(_imageIndices.count(), _triggerIndices.count()); maxIndex = std::min(maxIndex, _imageList.count()); for(int i = 0; i < maxIndex; i++) { + int imageIndex = _imageIndices[i]; + if (imageIndex >= _imageList.count()) { + emit error(tr("Geotagging failed. Image requested not present.")); + return; + } QFile fileRead(_imageList.at(_imageIndices[i]).absoluteFilePath()); if (!fileRead.open(QIODevice::ReadOnly)) { emit error(tr("Geotagging failed. Couldn't open an image.")); From 17650954fdcb991ed84f3aa07ef95df2a930bdca Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Wed, 4 Apr 2018 09:08:08 -0700 Subject: [PATCH 04/11] Fix parsing order --- src/AnalyzeView/ULogParser.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AnalyzeView/ULogParser.cc b/src/AnalyzeView/ULogParser.cc index 8a7e172..806dfd0 100644 --- a/src/AnalyzeView/ULogParser.cc +++ b/src/AnalyzeView/ULogParser.cc @@ -139,15 +139,10 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList Date: Sat, 7 Apr 2018 10:04:00 -0700 Subject: [PATCH 05/11] Better debugging --- src/AnalyzeView/LogDownloadController.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnalyzeView/LogDownloadController.cc b/src/AnalyzeView/LogDownloadController.cc index 57fab39..b41e1fb 100644 --- a/src/AnalyzeView/LogDownloadController.cc +++ b/src/AnalyzeView/LogDownloadController.cc @@ -320,7 +320,7 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui if(ofs <= _downloadData->entry->size()) { const uint32_t chunk = ofs / kChunkSize; if (chunk != _downloadData->current_chunk) { - qWarning() << "Ignored packet for out of order chunk" << chunk; + qWarning() << "Ignored packet for out of order chunk actual:expected" << chunk << _downloadData->current_chunk; return; } const uint16_t bin = (ofs - chunk*kChunkSize) / MAVLINK_MSG_LOG_DATA_FIELD_DATA_LEN; From 7a00ffc69f7f459b0f7196ddd61ab4161b8e72c2 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Sat, 7 Apr 2018 10:04:10 -0700 Subject: [PATCH 06/11] Save to correct location --- src/AnalyzeView/LogDownloadPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnalyzeView/LogDownloadPage.qml b/src/AnalyzeView/LogDownloadPage.qml index f2b684d..4b3d35a 100644 --- a/src/AnalyzeView/LogDownloadPage.qml +++ b/src/AnalyzeView/LogDownloadPage.qml @@ -155,7 +155,7 @@ AnalyzePage { fileDialog.qgcView = logDownloadPage fileDialog.title = qsTr("Select save directory") fileDialog.selectExisting = true - fileDialog.folder = QGroundControl.settingsManager.appSettings.telemetrySavePath + fileDialog.folder = QGroundControl.settingsManager.appSettings.logSavePath fileDialog.selectFolder = true fileDialog.openForLoad() } From c12a8cf5bb12f92797b984a15493518804e1a769 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Sat, 7 Apr 2018 13:59:56 -0700 Subject: [PATCH 07/11] Add Crash Log Directory --- src/Settings/AppSettings.cc | 77 +++++++++++++++++++++++---------------------- src/Settings/AppSettings.h | 3 ++ 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/Settings/AppSettings.cc b/src/Settings/AppSettings.cc index 3e8b950..1b9c736 100644 --- a/src/Settings/AppSettings.cc +++ b/src/Settings/AppSettings.cc @@ -53,30 +53,31 @@ const char* AppSettings::telemetryDirectory = "Telemetry"; const char* AppSettings::missionDirectory = "Missions"; const char* AppSettings::logDirectory = "Logs"; const char* AppSettings::videoDirectory = "Video"; +const char* AppSettings::crashDirectory = "CrashLogs"; AppSettings::AppSettings(QObject* parent) - : SettingsGroup(appSettingsGroupName, QString() /* root settings group */, parent) - , _offlineEditingFirmwareTypeFact(NULL) - , _offlineEditingVehicleTypeFact(NULL) - , _offlineEditingCruiseSpeedFact(NULL) - , _offlineEditingHoverSpeedFact(NULL) - , _offlineEditingAscentSpeedFact(NULL) - , _offlineEditingDescentSpeedFact(NULL) - , _batteryPercentRemainingAnnounceFact(NULL) - , _defaultMissionItemAltitudeFact(NULL) - , _telemetrySaveFact(NULL) - , _telemetrySaveNotArmedFact(NULL) - , _audioMutedFact(NULL) - , _virtualJoystickFact(NULL) - , _appFontPointSizeFact(NULL) - , _indoorPaletteFact(NULL) - , _showLargeCompassFact(NULL) - , _savePathFact(NULL) - , _autoLoadMissionsFact(NULL) - , _mapboxTokenFact(NULL) - , _esriTokenFact(NULL) - , _defaultFirmwareTypeFact(NULL) - , _gstDebugFact(NULL) + : SettingsGroup (appSettingsGroupName, QString() /* root settings group */, parent) + , _offlineEditingFirmwareTypeFact (NULL) + , _offlineEditingVehicleTypeFact (NULL) + , _offlineEditingCruiseSpeedFact (NULL) + , _offlineEditingHoverSpeedFact (NULL) + , _offlineEditingAscentSpeedFact (NULL) + , _offlineEditingDescentSpeedFact (NULL) + , _batteryPercentRemainingAnnounceFact (NULL) + , _defaultMissionItemAltitudeFact (NULL) + , _telemetrySaveFact (NULL) + , _telemetrySaveNotArmedFact (NULL) + , _audioMutedFact (NULL) + , _virtualJoystickFact (NULL) + , _appFontPointSizeFact (NULL) + , _indoorPaletteFact (NULL) + , _showLargeCompassFact (NULL) + , _savePathFact (NULL) + , _autoLoadMissionsFact (NULL) + , _mapboxTokenFact (NULL) + , _esriTokenFact (NULL) + , _defaultFirmwareTypeFact (NULL) + , _gstDebugFact (NULL) { QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "AppSettings", "Reference only"); @@ -118,6 +119,7 @@ void AppSettings::_checkSavePathDirectories(void) savePathDir.mkdir(missionDirectory); savePathDir.mkdir(logDirectory); savePathDir.mkdir(videoDirectory); + savePathDir.mkdir(crashDirectory); } } @@ -279,67 +281,68 @@ Fact* AppSettings::savePath(void) QString AppSettings::missionSavePath(void) { - QString fullPath; - QString path = savePath()->rawValue().toString(); if (!path.isEmpty() && QDir(path).exists()) { QDir dir(path); return dir.filePath(missionDirectory); } - return fullPath; + return QString(); } QString AppSettings::parameterSavePath(void) { - QString fullPath; - QString path = savePath()->rawValue().toString(); if (!path.isEmpty() && QDir(path).exists()) { QDir dir(path); return dir.filePath(parameterDirectory); } - return fullPath; + return QString(); } QString AppSettings::telemetrySavePath(void) { - QString fullPath; - QString path = savePath()->rawValue().toString(); if (!path.isEmpty() && QDir(path).exists()) { QDir dir(path); return dir.filePath(telemetryDirectory); } - return fullPath; + return QString(); } QString AppSettings::logSavePath(void) { - QString fullPath; - QString path = savePath()->rawValue().toString(); if (!path.isEmpty() && QDir(path).exists()) { QDir dir(path); return dir.filePath(logDirectory); } - return fullPath; + return QString(); } QString AppSettings::videoSavePath(void) { - QString fullPath; - QString path = savePath()->rawValue().toString(); if (!path.isEmpty() && QDir(path).exists()) { QDir dir(path); return dir.filePath(videoDirectory); } - return fullPath; + return QString(); +} + +QString AppSettings::crashSavePath(void) +{ + QString path = savePath()->rawValue().toString(); + if (!path.isEmpty() && QDir(path).exists()) { + QDir dir(path); + return dir.filePath(crashDirectory); + } + + return QString(); } Fact* AppSettings::autoLoadMissions(void) diff --git a/src/Settings/AppSettings.h b/src/Settings/AppSettings.h index 6b421aa..108f665 100644 --- a/src/Settings/AppSettings.h +++ b/src/Settings/AppSettings.h @@ -47,6 +47,7 @@ public: Q_PROPERTY(QString telemetrySavePath READ telemetrySavePath NOTIFY savePathsChanged) Q_PROPERTY(QString logSavePath READ logSavePath NOTIFY savePathsChanged) Q_PROPERTY(QString videoSavePath READ videoSavePath NOTIFY savePathsChanged) + Q_PROPERTY(QString crashSavePath READ crashSavePath NOTIFY savePathsChanged) Q_PROPERTY(QString planFileExtension MEMBER planFileExtension CONSTANT) Q_PROPERTY(QString missionFileExtension MEMBER missionFileExtension CONSTANT) @@ -83,6 +84,7 @@ public: QString telemetrySavePath (void); QString logSavePath (void); QString videoSavePath (void); + QString crashSavePath (void); static MAV_AUTOPILOT offlineEditingFirmwareTypeFromFirmwareType(MAV_AUTOPILOT firmwareType); static MAV_TYPE offlineEditingVehicleTypeFromVehicleType(MAV_TYPE vehicleType); @@ -128,6 +130,7 @@ public: static const char* missionDirectory; static const char* logDirectory; static const char* videoDirectory; + static const char* crashDirectory; signals: void savePathsChanged(void); From 82c0424ebaae33ccfe6e0d63940cb6b1fd9d8d2f Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Sun, 8 Apr 2018 13:10:07 -0700 Subject: [PATCH 08/11] Much better error reporting --- src/AnalyzeView/GeoTagController.cc | 33 ++++++++++++++++++--------------- src/AnalyzeView/GeoTagController.h | 5 +++-- src/AnalyzeView/GeoTagPage.qml | 5 +++-- src/AnalyzeView/ULogParser.cc | 8 +++++--- src/AnalyzeView/ULogParser.h | 7 ++++++- 5 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/AnalyzeView/GeoTagController.cc b/src/AnalyzeView/GeoTagController.cc index 2db65e7..3f0627d 100644 --- a/src/AnalyzeView/GeoTagController.cc +++ b/src/AnalyzeView/GeoTagController.cc @@ -70,8 +70,7 @@ void GeoTagController::startTagging(void) QDir imageDirectory = QDir(_worker.imageDirectory()); if(!imageDirectory.exists()) { - _errorMessage = tr("Cannot find the image directory"); - emit errorMessageChanged(_errorMessage); + _setErrorMessage(tr("Cannot find the image directory")); return; } if(_worker.saveDirectory() == "") { @@ -83,23 +82,20 @@ void GeoTagController::startTagging(void) msgBox.setWindowModality(Qt::ApplicationModal); msgBox.addButton(tr("Replace"), QMessageBox::ActionRole); if (msgBox.exec() == QMessageBox::Cancel) { - _errorMessage = tr("Images have already been tagged"); - emit errorMessageChanged(_errorMessage); + _setErrorMessage(tr("Images have already been tagged")); return; } QDir oldTaggedFolder = QDir(_worker.imageDirectory() + "/TAGGED"); oldTaggedFolder.removeRecursively(); if(!imageDirectory.mkdir(_worker.imageDirectory() + "/TAGGED")) { - _errorMessage = tr("Couldn't replace the previously tagged images"); - emit errorMessageChanged(_errorMessage); + _setErrorMessage(tr("Couldn't replace the previously tagged images")); return; } } } else { QDir saveDirectory = QDir(_worker.saveDirectory()); if(!saveDirectory.exists()) { - _errorMessage = tr("Cannot find the save directory"); - emit errorMessageChanged(_errorMessage); + _setErrorMessage(tr("Cannot find the save directory")); return; } saveDirectory.setFilter(QDir::Files | QDir::Readable | QDir::NoSymLinks | QDir::Writable); @@ -115,15 +111,13 @@ void GeoTagController::startTagging(void) msgBox.setWindowModality(Qt::ApplicationModal); msgBox.addButton(tr("Replace"), QMessageBox::ActionRole); if (msgBox.exec() == QMessageBox::Cancel) { - _errorMessage = tr("Save folder not empty"); - emit errorMessageChanged(_errorMessage); + _setErrorMessage(tr("Save folder not empty")); return; } foreach(QString dirFile, imageList) { if(!saveDirectory.remove(dirFile)) { - _errorMessage = tr("Couldn't replace the existing images"); - emit errorMessageChanged(_errorMessage); + _setErrorMessage(tr("Couldn't replace the existing images")); return; } } @@ -144,6 +138,13 @@ void GeoTagController::_workerError(QString errorMessage) emit errorMessageChanged(errorMessage); } + +void GeoTagController::_setErrorMessage(const QString& error) +{ + _errorMessage = error; + emit errorMessageChanged(error); +} + GeoTagWorker::GeoTagWorker(void) : _cancel(false) , _logFile("") @@ -210,9 +211,10 @@ void GeoTagWorker::run(void) // Instantiate appropriate parser _triggerList.clear(); bool parseComplete = false; - if(isULog) { + QString errorString; + if (isULog) { ULogParser parser; - parseComplete = parser.getTagsFromLog(log, _triggerList); + parseComplete = parser.getTagsFromLog(log, _triggerList, errorString); } else { PX4LogParser parser; @@ -227,7 +229,8 @@ void GeoTagWorker::run(void) return; } else { qCDebug(GeotaggingLog) << "Log parsing failed"; - emit error(tr("Log parsing failed - tagging cancelled")); + errorString = tr("%1 - tagging cancelled").arg(errorString.isEmpty() ? tr("Log parsing failed") : errorString); + emit error(errorString); return; } } diff --git a/src/AnalyzeView/GeoTagController.h b/src/AnalyzeView/GeoTagController.h index aee58f6..f3955d2 100644 --- a/src/AnalyzeView/GeoTagController.h +++ b/src/AnalyzeView/GeoTagController.h @@ -117,8 +117,9 @@ signals: void errorMessageChanged (QString errorMessage); private slots: - void _workerProgressChanged(double progress); - void _workerError(QString errorMsg); + void _workerProgressChanged (double progress); + void _workerError (QString errorMsg); + void _setErrorMessage (const QString& error); private: QString _errorMessage; diff --git a/src/AnalyzeView/GeoTagPage.qml b/src/AnalyzeView/GeoTagPage.qml index dbaa678..dcc4bb5 100644 --- a/src/AnalyzeView/GeoTagPage.qml +++ b/src/AnalyzeView/GeoTagPage.qml @@ -124,8 +124,9 @@ AnalyzePage { } QGCButton { - text: geoController.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging") - width: ScreenTools.defaultFontPixelWidth * 30 + text: geoController.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging") + width: ScreenTools.defaultFontPixelWidth * 30 + onClicked: { if (geoController.inProgress) { geoController.cancelTagging() diff --git a/src/AnalyzeView/ULogParser.cc b/src/AnalyzeView/ULogParser.cc index 806dfd0..d6b7f36 100644 --- a/src/AnalyzeView/ULogParser.cc +++ b/src/AnalyzeView/ULogParser.cc @@ -86,11 +86,13 @@ bool ULogParser::parseFieldFormat(QString& fields) return false; } -bool ULogParser::getTagsFromLog(QByteArray& log, QList& cameraFeedback) +bool ULogParser::getTagsFromLog(QByteArray& log, QList& cameraFeedback, QString& errorMessage) { + errorMessage.clear(); + //verify it's an ULog file if(!log.contains(_ULogMagic)) { - qWarning() << "Could not detect ULog file header magic"; + errorMessage = tr("Could not detect ULog file header magic"); return false; } @@ -175,7 +177,7 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList #include +#include #include "GeoTagController.h" @@ -10,10 +11,14 @@ class ULogParser { + Q_DECLARE_TR_FUNCTIONS(ULogParser) + public: ULogParser(); ~ULogParser(); - bool getTagsFromLog(QByteArray& log, QList& cameraFeedback); + + /// @return true: failed, errorMessage set + bool getTagsFromLog(QByteArray& log, QList& cameraFeedback, QString& errorMessage); private: From ed2f294c69e979641c718fba018fba5ecc14328b Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Wed, 11 Apr 2018 13:45:30 -0700 Subject: [PATCH 09/11] Better guarding against crashes --- src/comm/BluetoothLink.cc | 33 +++++++-------- src/comm/SerialLink.cc | 27 ++++++------ src/comm/TCPLink.cc | 30 +++++++------- src/comm/UDPLink.cc | 102 +++++++++++++++++++++++----------------------- 4 files changed, 96 insertions(+), 96 deletions(-) diff --git a/src/comm/BluetoothLink.cc b/src/comm/BluetoothLink.cc index f1b9cc4..b6e2009 100644 --- a/src/comm/BluetoothLink.cc +++ b/src/comm/BluetoothLink.cc @@ -75,30 +75,25 @@ QString BluetoothLink::getName() const void BluetoothLink::_writeBytes(const QByteArray bytes) { - if(_targetSocket) - { - if(_targetSocket->isWritable()) - { - if(_targetSocket->write(bytes) > 0) { - _logOutputDataRate(bytes.size(), QDateTime::currentMSecsSinceEpoch()); - } - else - qWarning() << "Bluetooth write error"; + if (_targetSocket) { + if(_targetSocket->write(bytes) > 0) { + _logOutputDataRate(bytes.size(), QDateTime::currentMSecsSinceEpoch()); + } else { + qWarning() << "Bluetooth write error"; } - else - qWarning() << "Bluetooth not writable error"; } } void BluetoothLink::readBytes() { - while (_targetSocket->bytesAvailable() > 0) - { - QByteArray datagram; - datagram.resize(_targetSocket->bytesAvailable()); - _targetSocket->read(datagram.data(), datagram.size()); - emit bytesReceived(this, datagram); - _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); + if (_targetSocket) { + while (_targetSocket->bytesAvailable() > 0) { + QByteArray datagram; + datagram.resize(_targetSocket->bytesAvailable()); + _targetSocket->read(datagram.data(), datagram.size()); + emit bytesReceived(this, datagram); + _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); + } } } @@ -114,7 +109,7 @@ void BluetoothLink::_disconnect(void) #endif if(_targetSocket) { - delete _targetSocket; + _targetSocket->deleteLater(); _targetSocket = NULL; emit disconnected(); } diff --git a/src/comm/SerialLink.cc b/src/comm/SerialLink.cc index 3ae34a3..be016ac 100644 --- a/src/comm/SerialLink.cc +++ b/src/comm/SerialLink.cc @@ -57,10 +57,6 @@ void SerialLink::requestReset() SerialLink::~SerialLink() { _disconnect(); - if (_port) { - delete _port; - } - _port = NULL; } bool SerialLink::_isBootloader() @@ -92,6 +88,7 @@ void SerialLink::_writeBytes(const QByteArray data) _port->write(data); } else { // Error occurred + qWarning() << "Serial port not writeable"; _emitLinkError(tr("Could not send data - link %1 is disconnected!").arg(getName())); } } @@ -105,7 +102,7 @@ void SerialLink::_disconnect(void) { if (_port) { _port->close(); - delete _port; + _port->deleteLater(); _port = NULL; } @@ -199,7 +196,7 @@ bool SerialLink::_hardwareConnect(QSerialPort::SerialPortError& error, QString& } } - _port = new QSerialPort(_serialConfig->portName()); + _port = new QSerialPort(_serialConfig->portName(), this); QObject::connect(_port, static_cast(&QSerialPort::error), this, &SerialLink::linkError); @@ -261,12 +258,18 @@ bool SerialLink::_hardwareConnect(QSerialPort::SerialPortError& error, QString& void SerialLink::_readBytes(void) { - qint64 byteCount = _port->bytesAvailable(); - if (byteCount) { - QByteArray buffer; - buffer.resize(byteCount); - _port->read(buffer.data(), buffer.size()); - emit bytesReceived(this, buffer); + if (_port && _port->isOpen()) { + qint64 byteCount = _port->bytesAvailable(); + if (byteCount) { + QByteArray buffer; + buffer.resize(byteCount); + _port->read(buffer.data(), buffer.size()); + emit bytesReceived(this, buffer); + } + } else { + // Error occurred + qWarning() << "Serial port not readable"; + _emitLinkError(tr("Could not read data - link %1 is disconnected!").arg(getName())); } } diff --git a/src/comm/TCPLink.cc b/src/comm/TCPLink.cc index 5760fb7..d91cdb1 100644 --- a/src/comm/TCPLink.cc +++ b/src/comm/TCPLink.cc @@ -78,11 +78,11 @@ void TCPLink::_writeBytes(const QByteArray data) #ifdef TCPLINK_READWRITE_DEBUG _writeDebugBytes(data); #endif - if (!_socket) - return; - _socket->write(data); - _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch()); + if (_socket) { + _socket->write(data); + _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch()); + } } /** @@ -93,17 +93,19 @@ void TCPLink::_writeBytes(const QByteArray data) **/ void TCPLink::readBytes() { - qint64 byteCount = _socket->bytesAvailable(); - if (byteCount) - { - QByteArray buffer; - buffer.resize(byteCount); - _socket->read(buffer.data(), buffer.size()); - emit bytesReceived(this, buffer); - _logInputDataRate(byteCount, QDateTime::currentMSecsSinceEpoch()); + if (_socket) { + qint64 byteCount = _socket->bytesAvailable(); + if (byteCount) + { + QByteArray buffer; + buffer.resize(byteCount); + _socket->read(buffer.data(), buffer.size()); + emit bytesReceived(this, buffer); + _logInputDataRate(byteCount, QDateTime::currentMSecsSinceEpoch()); #ifdef TCPLINK_READWRITE_DEBUG - writeDebugBytes(buffer.data(), buffer.size()); + writeDebugBytes(buffer.data(), buffer.size()); #endif + } } } @@ -118,9 +120,9 @@ void TCPLink::_disconnect(void) wait(); if (_socket) { _socketIsConnected = false; - _socket->deleteLater(); // Make sure delete happens on correct thread _socket->disconnectFromHost(); // Disconnect tcp _socket->waitForDisconnected(); + _socket->deleteLater(); // Make sure delete happens on correct thread _socket = NULL; emit disconnected(); } diff --git a/src/comm/UDPLink.cc b/src/comm/UDPLink.cc index ab91418..803cbf0 100644 --- a/src/comm/UDPLink.cc +++ b/src/comm/UDPLink.cc @@ -136,36 +136,35 @@ void UDPLink::removeHost(const QString& host) void UDPLink::_writeBytes(const QByteArray data) { - if (!_socket) - return; - - QStringList goneHosts; - // Send to all connected systems - QString host; - int port; - if(_udpConfig->firstHost(host, port)) { - do { - QHostAddress currentHost(host); - if(_socket->writeDatagram(data, currentHost, (quint16)port) < 0) { - // This host is gone. Add to list to be removed - // We should keep track of hosts that were manually added (static) and - // hosts that were added because we heard from them (dynamic). Only - // dynamic hosts should be removed and even then, after a few tries, not - // the first failure. In the mean time, we don't remove anything. - if(REMOVE_GONE_HOSTS) { - goneHosts.append(host); + if (_socket) { + QStringList goneHosts; + // Send to all connected systems + QString host; + int port; + if(_udpConfig->firstHost(host, port)) { + do { + QHostAddress currentHost(host); + if(_socket->writeDatagram(data, currentHost, (quint16)port) < 0) { + // This host is gone. Add to list to be removed + // We should keep track of hosts that were manually added (static) and + // hosts that were added because we heard from them (dynamic). Only + // dynamic hosts should be removed and even then, after a few tries, not + // the first failure. In the mean time, we don't remove anything. + if(REMOVE_GONE_HOSTS) { + goneHosts.append(host); + } + } else { + // Only log rate if data actually got sent. Not sure about this as + // "host not there" takes time too regardless of size of data. In fact, + // 1 byte or "UDP frame size" bytes are the same as that's the data + // unit sent by UDP. + _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch()); } - } else { - // Only log rate if data actually got sent. Not sure about this as - // "host not there" takes time too regardless of size of data. In fact, - // 1 byte or "UDP frame size" bytes are the same as that's the data - // unit sent by UDP. - _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch()); + } while (_udpConfig->nextHost(host, port)); + //-- Remove hosts that are no longer there + foreach (const QString& ghost, goneHosts) { + _udpConfig->removeHost(ghost); } - } while (_udpConfig->nextHost(host, port)); - //-- Remove hosts that are no longer there - foreach (const QString& ghost, goneHosts) { - _udpConfig->removeHost(ghost); } } } @@ -175,30 +174,31 @@ void UDPLink::_writeBytes(const QByteArray data) **/ void UDPLink::readBytes() { - QByteArray databuffer; - while (_socket->hasPendingDatagrams()) - { - QByteArray datagram; - datagram.resize(_socket->pendingDatagramSize()); - QHostAddress sender; - quint16 senderPort; - _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); - databuffer.append(datagram); - //-- Wait a bit before sending it over - if(databuffer.size() > 10 * 1024) { + if (_socket) { + QByteArray databuffer; + while (_socket->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(_socket->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); + databuffer.append(datagram); + //-- Wait a bit before sending it over + if(databuffer.size() > 10 * 1024) { + emit bytesReceived(this, databuffer); + databuffer.clear(); + } + _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); + // TODO This doesn't validade the sender. Anything sending UDP packets to this port gets + // added to the list and will start receiving datagrams from here. Even a port scanner + // would trigger this. + // Add host to broadcast list if not yet present, or update its port + _udpConfig->addHost(sender.toString(), (int)senderPort); + } + //-- Send whatever is left + if(databuffer.size()) { emit bytesReceived(this, databuffer); - databuffer.clear(); } - _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); - // TODO This doesn't validade the sender. Anything sending UDP packets to this port gets - // added to the list and will start receiving datagrams from here. Even a port scanner - // would trigger this. - // Add host to broadcast list if not yet present, or update its port - _udpConfig->addHost(sender.toString(), (int)senderPort); - } - //-- Send whatever is left - if(databuffer.size()) { - emit bytesReceived(this, databuffer); } } @@ -246,7 +246,7 @@ bool UDPLink::_hardwareConnect() _socket = NULL; } QHostAddress host = QHostAddress::AnyIPv4; - _socket = new QUdpSocket(); + _socket = new QUdpSocket(this); _socket->setProxy(QNetworkProxy::NoProxy); _connectState = _socket->bind(host, _udpConfig->localPort(), QAbstractSocket::ReuseAddressHint | QUdpSocket::ShareAddress); if (_connectState) { From 8b8a55c20ac7e89d0117aa0ad18871e0a4accba2 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Mon, 16 Apr 2018 11:33:49 -0700 Subject: [PATCH 10/11] Fix merge conflict --- src/AnalyzeView/ULogParser.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/AnalyzeView/ULogParser.cc b/src/AnalyzeView/ULogParser.cc index ebe76dd..d6b7f36 100644 --- a/src/AnalyzeView/ULogParser.cc +++ b/src/AnalyzeView/ULogParser.cc @@ -177,11 +177,7 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList>>>>>> b4f4085c6733b934358b00389d734600eab87bf7 return false; } From a76dd63b1e0973da4b45f5db04daf09db51d1a14 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Mon, 16 Apr 2018 12:29:04 -0700 Subject: [PATCH 11/11] Merge conflict fix --- src/comm/UDPLink.cc | 72 +++++++++++------------------------------------------ 1 file changed, 15 insertions(+), 57 deletions(-) diff --git a/src/comm/UDPLink.cc b/src/comm/UDPLink.cc index b2ba5ea..36b2a1a 100644 --- a/src/comm/UDPLink.cc +++ b/src/comm/UDPLink.cc @@ -160,7 +160,6 @@ QString UDPLink::getName() const void UDPLink::_writeBytes(const QByteArray data) { -<<<<<<< HEAD if (!_socket) return; // Send to all manually targeted systems @@ -168,37 +167,6 @@ void UDPLink::_writeBytes(const QByteArray data) // Skip it if it's part of the session clients below if(!contains_target(_sessionTargets, target->address, target->port)) { _writeDataGram(data, target); -======= - if (_socket) { - QStringList goneHosts; - // Send to all connected systems - QString host; - int port; - if(_udpConfig->firstHost(host, port)) { - do { - QHostAddress currentHost(host); - if(_socket->writeDatagram(data, currentHost, (quint16)port) < 0) { - // This host is gone. Add to list to be removed - // We should keep track of hosts that were manually added (static) and - // hosts that were added because we heard from them (dynamic). Only - // dynamic hosts should be removed and even then, after a few tries, not - // the first failure. In the mean time, we don't remove anything. - if(REMOVE_GONE_HOSTS) { - goneHosts.append(host); - } - } else { - // Only log rate if data actually got sent. Not sure about this as - // "host not there" takes time too regardless of size of data. In fact, - // 1 byte or "UDP frame size" bytes are the same as that's the data - // unit sent by UDP. - _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch()); - } - } while (_udpConfig->nextHost(host, port)); - //-- Remove hosts that are no longer there - foreach (const QString& ghost, goneHosts) { - _udpConfig->removeHost(ghost); - } ->>>>>>> b4f4085c6733b934358b00389d734600eab87bf7 } } // Send to all connected systems @@ -226,31 +194,23 @@ void UDPLink::_writeDataGram(const QByteArray data, const UDPCLient* target) void UDPLink::readBytes() { if (_socket) { - QByteArray databuffer; - while (_socket->hasPendingDatagrams()) { - QByteArray datagram; - datagram.resize(_socket->pendingDatagramSize()); - QHostAddress sender; - quint16 senderPort; - _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); - databuffer.append(datagram); - //-- Wait a bit before sending it over - if(databuffer.size() > 10 * 1024) { - emit bytesReceived(this, databuffer); - databuffer.clear(); - } - _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); - // TODO This doesn't validade the sender. Anything sending UDP packets to this port gets - // added to the list and will start receiving datagrams from here. Even a port scanner - // would trigger this. - // Add host to broadcast list if not yet present, or update its port - _udpConfig->addHost(sender.toString(), (int)senderPort); - } - //-- Send whatever is left - if(databuffer.size()) { + return; + } + + QByteArray databuffer; + while (_socket->hasPendingDatagrams()) + { + QByteArray datagram; + datagram.resize(_socket->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); + databuffer.append(datagram); + //-- Wait a bit before sending it over + if(databuffer.size() > 10 * 1024) { emit bytesReceived(this, databuffer); + databuffer.clear(); } -<<<<<<< HEAD _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); // TODO: This doesn't validade the sender. Anything sending UDP packets to this port gets // added to the list and will start receiving datagrams from here. Even a port scanner @@ -269,8 +229,6 @@ void UDPLink::readBytes() //-- Send whatever is left if(databuffer.size()) { emit bytesReceived(this, databuffer); -======= ->>>>>>> b4f4085c6733b934358b00389d734600eab87bf7 } }