diff --git a/QOpenHD.pro b/QOpenHD.pro index 3d0ef89d6..b8a5680fd 100755 --- a/QOpenHD.pro +++ b/QOpenHD.pro @@ -71,6 +71,7 @@ LinuxBuild { QT +=core quick qml gui \ widgets QT += opengl +QT += charts INCLUDEPATH += $$PWD/lib INCLUDEPATH += $$PWD/app diff --git a/app/main.cpp b/app/main.cpp index ae7f34f9f..78e54a93f 100755 --- a/app/main.cpp +++ b/app/main.cpp @@ -390,16 +390,15 @@ int main(int argc, char *argv[]) { QtAndroid::hideSplashScreen(); #endif - qDebug() << "Running QML"; + qDebug() << "QML loaded"; // Now we start mavlink for the first time MavlinkTelemetry::instance().start(); QRenderStats::instance().register_to_root_window(engine); - LogMessagesModel::instanceGround().addLogMessage("QOpenHD","running"); const int retval = app.exec(); - + // Terminating needs a bit of special care due to the singleton usage and threads + qDebug()<<"Terminating"; + MavlinkTelemetry::instance().terminate(); return retval; - - } diff --git a/app/telemetry/MavlinkTelemetry.cpp b/app/telemetry/MavlinkTelemetry.cpp index c656f5f6c..2bd491822 100644 --- a/app/telemetry/MavlinkTelemetry.cpp +++ b/app/telemetry/MavlinkTelemetry.cpp @@ -38,13 +38,27 @@ void MavlinkTelemetry::start() m_heartbeat_thread=std::make_unique(&MavlinkTelemetry::send_heartbeat_loop,this); } -MavlinkTelemetry::~MavlinkTelemetry() +void MavlinkTelemetry::terminate() { + // first stop any incoming telemetry if(m_heartbeat_thread){ m_heartbeat_thread_run=false; m_heartbeat_thread->join(); m_heartbeat_thread=nullptr; } + m_udp_connection=nullptr; + m_tcp_connection=nullptr; + // Cleanup those 2 threads + CmdSender::instance().terminate(); + XParam::instance().terminate(); + qDebug()<<"MavlinkTelemetry::stopped"; +} + +MavlinkTelemetry::~MavlinkTelemetry() +{ + qDebug()<<"MavlinkTelemetry::~() begin"; + terminate(); + qDebug()<<"MavlinkTelemetry::~() end"; } MavlinkTelemetry &MavlinkTelemetry::instance() diff --git a/app/telemetry/MavlinkTelemetry.h b/app/telemetry/MavlinkTelemetry.h index d234499f0..edef2c436 100644 --- a/app/telemetry/MavlinkTelemetry.h +++ b/app/telemetry/MavlinkTelemetry.h @@ -35,7 +35,10 @@ class MavlinkTelemetry : public QObject MavlinkTelemetry(QObject *parent = nullptr); ~MavlinkTelemetry(); static MavlinkTelemetry& instance(); + // start / terminate needs a bit of care due to singleton usage, + // not clean, but works void start(); + void terminate(); /** * Send a message to the OHD ground unit. If no connection has been established (yet), this should return immediately. * The message can be aimed at either the OHD ground unit, the OHD air unit (forwarded by OpenHD) or the FC connected to the diff --git a/app/telemetry/action/impl/cmdsender.cpp b/app/telemetry/action/impl/cmdsender.cpp index 8200816e2..5954408d3 100644 --- a/app/telemetry/action/impl/cmdsender.cpp +++ b/app/telemetry/action/impl/cmdsender.cpp @@ -16,9 +16,16 @@ CmdSender::CmdSender() CmdSender::~CmdSender() { - m_timeout_thread_run=false; - m_timeout_thread->join(); - m_timeout_thread=nullptr; + terminate(); +} + +void CmdSender::terminate() +{ + if(m_timeout_thread){ + m_timeout_thread_run=false; + m_timeout_thread->join(); + m_timeout_thread=nullptr; + } } CmdSender &CmdSender::instance() @@ -178,7 +185,7 @@ void CmdSender::send_mavlink_command_long(const mavlink_command_long_t &cmd) void CmdSender::loop_timeout() { - while(true){ + while(m_timeout_thread_run){ std::this_thread::sleep_for(std::chrono::milliseconds(100)); handle_timeout(); } diff --git a/app/telemetry/action/impl/cmdsender.h b/app/telemetry/action/impl/cmdsender.h index 7a14704dc..bb8483e37 100644 --- a/app/telemetry/action/impl/cmdsender.h +++ b/app/telemetry/action/impl/cmdsender.h @@ -18,6 +18,7 @@ class CmdSender public: CmdSender(); ~CmdSender(); + void terminate(); static CmdSender& instance(); /** * returns true if this message has been consumed, false otherwise. diff --git a/app/telemetry/action/impl/xparam.cpp b/app/telemetry/action/impl/xparam.cpp index 712989ae3..6c8f78c55 100644 --- a/app/telemetry/action/impl/xparam.cpp +++ b/app/telemetry/action/impl/xparam.cpp @@ -17,9 +17,16 @@ XParam::XParam() XParam::~XParam() { - m_timeout_thread_run=false; - m_timeout_thread->join(); - m_timeout_thread=nullptr; + terminate(); +} + +void XParam::terminate() +{ + if(m_timeout_thread){ + m_timeout_thread_run=false; + m_timeout_thread->join(); + m_timeout_thread=nullptr; + } } XParam &XParam::instance() @@ -400,7 +407,7 @@ void XParam::update_progress_get_all(const RunningParamCmdGetAll &cmd) void XParam::loop_timeout() { - while(true){ + while(m_timeout_thread_run){ std::this_thread::sleep_for(std::chrono::milliseconds(100)); check_timeout_param_get_all(); check_timeout_param_set(); diff --git a/app/telemetry/action/impl/xparam.h b/app/telemetry/action/impl/xparam.h index b80b7da44..ecc7ed95a 100644 --- a/app/telemetry/action/impl/xparam.h +++ b/app/telemetry/action/impl/xparam.h @@ -16,6 +16,7 @@ class XParam public: explicit XParam(); ~XParam(); + void terminate(); static XParam& instance(); /** * returns true if this message has been consumed, false otherwise. diff --git a/app/telemetry/settings/documentedparam.cpp b/app/telemetry/settings/documentedparam.cpp index f4fb3fda1..3647d3ae7 100644 --- a/app/telemetry/settings/documentedparam.cpp +++ b/app/telemetry/settings/documentedparam.cpp @@ -265,7 +265,10 @@ static std::vector> get_parameters_list(){ ); } append_int(ret,"VIDEO_CODEC", - ImprovedIntSetting::createEnum( std::vector{"h264","h265","mjpeg"}), + //NOTE: MJPEG has been removed intentionally, since we are going to eventually remove support for it in + //favour of h264 + // ,"mjpeg" + ImprovedIntSetting::createEnum( std::vector{"h264","h265"}), "Video codec. If your camera/ground station does not support HW accelerated encoding/decoding of the selected codec,it'l default to SW encode/decode. " "A reboot (air&ground) is recommended after changing this parameter." ); diff --git a/app/videostreaming/avcodec/avcodec_decoder.cpp b/app/videostreaming/avcodec/avcodec_decoder.cpp index 602486c2b..a67945f9a 100644 --- a/app/videostreaming/avcodec/avcodec_decoder.cpp +++ b/app/videostreaming/avcodec/avcodec_decoder.cpp @@ -100,6 +100,7 @@ void AVCodecDecoder::terminate() // Wait for everything to cleanup and stop decode_thread->join(); } + qDebug()<<"Decoding terminated"; } void AVCodecDecoder::timer_check_settings_changed_callback() @@ -158,7 +159,8 @@ void AVCodecDecoder::constant_decode() } } qDebug()<<"Decode stopped,restarting"; - std::this_thread::sleep_for(std::chrono::seconds(1)); + // wait a bit before starting again, to save CPU + if(!m_should_terminate)std::this_thread::sleep_for(std::chrono::seconds(1)); } } diff --git a/install_build_dep.sh b/install_build_dep.sh index f89ffdf6b..61cd0b315 100755 --- a/install_build_dep.sh +++ b/install_build_dep.sh @@ -42,7 +42,7 @@ PLATFORM_PACKAGES="qml-module-qt-labs-platform" if [[ "${QTTYPE}" == "custom" ]]; then apt install -y openhd-qt else - apt -y install qml-module-qtquick-controls2 libqt5texttospeech5-dev libqt5concurrent5 libqt5core5a libqt5dbus5 libqt5designer5 libqt5gui5 libqt5help5 libqt5location5 libqt5location5-plugins libqt5multimedia5 libqt5multimedia5-plugins libqt5multimediagsttools5 libqt5multimediawidgets5 libqt5network5 libqt5opengl5 libqt5opengl5-dev libqt5positioning5 libqt5positioning5-plugins libqt5positioningquick5 libqt5printsupport5 libqt5qml5 libqt5quick5 libqt5quickparticles5 libqt5quickshapes5 libqt5quicktest5 libqt5quickwidgets5 libqt5sensors5 libqt5sql5 libqt5sql5-sqlite libqt5svg5 libqt5test5 libqt5webchannel5 libqt5webkit5 libqt5widgets5 libqt5x11extras5 libqt5xml5 openshot-qt python3-pyqt5 python3-pyqt5.qtopengl python3-pyqt5.qtsvg python3-pyqt5.qtwebkit python3-pyqtgraph qml-module-qt-labs-settings qml-module-qtgraphicaleffects qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick-controls qml-module-qtquick-dialogs qml-module-qtquick-extras qml-module-qtquick-layouts qml-module-qtquick-privatewidgets qml-module-qtquick-shapes qml-module-qtquick-window2 qml-module-qtquick2 qt5-gtk-platformtheme qt5-qmake qt5-qmake-bin qt5-qmltooling-plugins qtbase5-dev qtbase5-dev-tools qtchooser qtdeclarative5-dev qtdeclarative5-dev-tools qtpositioning5-dev qttranslations5-l10n + apt -y install qml-module-qtquick-controls2 libqt5texttospeech5-dev libqt5concurrent5 libqt5core5a libqt5dbus5 libqt5designer5 libqt5gui5 libqt5help5 libqt5location5 libqt5location5-plugins libqt5multimedia5 libqt5multimedia5-plugins libqt5multimediagsttools5 libqt5multimediawidgets5 libqt5network5 libqt5opengl5 libqt5opengl5-dev libqt5positioning5 libqt5positioning5-plugins libqt5positioningquick5 libqt5printsupport5 libqt5qml5 libqt5quick5 libqt5quickparticles5 libqt5quickshapes5 libqt5quicktest5 libqt5quickwidgets5 libqt5sensors5 libqt5sql5 libqt5sql5-sqlite libqt5svg5 libqt5test5 libqt5webchannel5 libqt5webkit5 libqt5widgets5 libqt5x11extras5 libqt5xml5 openshot-qt python3-pyqt5 python3-pyqt5.qtopengl python3-pyqt5.qtsvg python3-pyqt5.qtwebkit python3-pyqtgraph qml-module-qt-labs-settings qml-module-qtgraphicaleffects qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick-controls qml-module-qtquick-dialogs qml-module-qtquick-extras qml-module-qtquick-layouts qml-module-qtquick-privatewidgets qml-module-qtquick-shapes qml-module-qtquick-window2 qml-module-qtquick2 qt5-gtk-platformtheme qt5-qmake qt5-qmake-bin qt5-qmltooling-plugins qtbase5-dev qtbase5-dev-tools qtchooser qtdeclarative5-dev qtdeclarative5-dev-tools qtpositioning5-dev qttranslations5-l10n libqt5charts5-dev fi # Install platform-specific packages diff --git a/qml/ui/configpopup/ConfigPopup.qml b/qml/ui/configpopup/ConfigPopup.qml index 86b1ed292..5a8f6956b 100644 --- a/qml/ui/configpopup/ConfigPopup.qml +++ b/qml/ui/configpopup/ConfigPopup.qml @@ -207,7 +207,6 @@ Rectangle { // On localhost, QOpenHD "automatically" connects due to udp localhost method ConfigPopupSidebarButton{ id: connect_button - visible: !_ohdSystemAir.is_alive && !_ohdSystemGround.is_alive m_icon_text: "\uf6ff" m_description_text: "Connect" m_selection_index: 5 diff --git a/qml/ui/configpopup/openhd_settings/LinkQuickPanel.qml b/qml/ui/configpopup/openhd_settings/LinkQuickPanel.qml index 75aaefe85..28c211778 100644 --- a/qml/ui/configpopup/openhd_settings/LinkQuickPanel.qml +++ b/qml/ui/configpopup/openhd_settings/LinkQuickPanel.qml @@ -14,8 +14,6 @@ import OpenHD 1.0 import "../../../ui" as Ui import "../../elements" -import QtCharts 2.0 - // This is an extra screen for changing the frequency / channel width - // They both need to match ! Rectangle{ diff --git a/qml/ui/configpopup/openhd_settings/PopupAnalyzeChannels.qml b/qml/ui/configpopup/openhd_settings/PopupAnalyzeChannels.qml index 63d40b0e2..4b13457ea 100644 --- a/qml/ui/configpopup/openhd_settings/PopupAnalyzeChannels.qml +++ b/qml/ui/configpopup/openhd_settings/PopupAnalyzeChannels.qml @@ -14,7 +14,7 @@ import OpenHD 1.0 import "../../../ui" as Ui import "../../elements" -import QtCharts 2.0 +import QtCharts 2.15 Rectangle{ id: main_background @@ -80,7 +80,7 @@ Rectangle{ color: closeButton.hovered ? "darkgrey" : "lightgrey" } onClicked: { - if (_ohdSystemGround.is_alive && _ohdSystemGround.wb_gnd_operating_mode == 1) { + if (_ohdSystemGround.is_alive && _ohdSystemGround.wb_gnd_operating_mode == 2) { _qopenhd.show_toast("STILL ANALYZING, PLEASE WAIT ..."); return; } @@ -90,7 +90,7 @@ Rectangle{ } RowLayout{ - visible:false + visible:true Layout.alignment: Qt.AlignTop | Qt.AlignRight ButtonIconInfo{ Layout.alignment: Qt.AlignLeft @@ -216,14 +216,6 @@ Rectangle{ } } } - /*Button{ - anchors.top: pollution_chart.top - anchors.left: pollution_chart.left - text: "ENLARGE" - onClicked: { - m_chart_enlarged = !m_chart_enlarged; - } - }*/ } // Filler //Item{ diff --git a/qml/ui/configpopup/openhd_settings/PopupScanChannels.qml b/qml/ui/configpopup/openhd_settings/PopupScanChannels.qml index fc886295c..98e28ed6d 100644 --- a/qml/ui/configpopup/openhd_settings/PopupScanChannels.qml +++ b/qml/ui/configpopup/openhd_settings/PopupScanChannels.qml @@ -78,19 +78,6 @@ Rectangle{ RowLayout{ id:channelSelectorRow Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - ComboBox { - Layout.preferredWidth: 400 - Layout.minimumWidth: 100 - id: comboBoxWhichFrequencyToScan - model: model_chann_to_scan - textRole: "title" - Material.background: { - (comboBoxWhichFrequencyToScan.currentIndex===0) ? "#2b9848" : "#ffae42" - } - onCurrentIndexChanged: { - } - enabled: _ohdSystemGround.is_alive && _ohdSystemGround.wb_gnd_operating_mode==0 - } Button{ text: "START" enabled: _ohdSystemGround.is_alive && _ohdSystemGround.wb_gnd_operating_mode==0 @@ -107,6 +94,20 @@ Rectangle{ } } } + + ComboBox { + Layout.preferredWidth: 400 + Layout.minimumWidth: 100 + id: comboBoxWhichFrequencyToScan + model: model_chann_to_scan + textRole: "title" + Material.background: { + (comboBoxWhichFrequencyToScan.currentIndex===0) ? "#2b9848" : "#ffae42" + } + onCurrentIndexChanged: { + } + enabled: _ohdSystemGround.is_alive && _ohdSystemGround.wb_gnd_operating_mode==0 + } ButtonIconInfo{ visible:false onClicked: { diff --git a/qml/ui/configpopup/qopenhd_settings/AppDevSettingsView.qml b/qml/ui/configpopup/qopenhd_settings/AppDevSettingsView.qml index 354ca2a18..64202d6e3 100755 --- a/qml/ui/configpopup/qopenhd_settings/AppDevSettingsView.qml +++ b/qml/ui/configpopup/qopenhd_settings/AppDevSettingsView.qml @@ -5,7 +5,6 @@ import QtQuick.Dialogs 1.0 import QtQuick.Controls.Material 2.12 import Qt.labs.settings 1.0 import Qt.labs.folderlistmodel 2.0 -import Qt.labs.platform 1.0 import OpenHD 1.0 diff --git a/qml/ui/elements/AppSettings.qml b/qml/ui/elements/AppSettings.qml index da4324369..83e623349 100644 --- a/qml/ui/elements/AppSettings.qml +++ b/qml/ui/elements/AppSettings.qml @@ -379,6 +379,7 @@ Settings { property bool wb_link_rate_control_widget_show_frequency: true property bool wb_link_rate_control_widget_show_bitrate: true property bool wb_link_rate_control_widget_show_fec_and_keyframe: true + property bool wb_link_rate_control_widget_show_throttle_warning: true property bool wb_link_rate_control_widget_show_bitrate_detailed: true diff --git a/qml/ui/elements/RestartQOpenHDMessageBox.qml b/qml/ui/elements/RestartQOpenHDMessageBox.qml index 457c348f5..a484135e1 100644 --- a/qml/ui/elements/RestartQOpenHDMessageBox.qml +++ b/qml/ui/elements/RestartQOpenHDMessageBox.qml @@ -28,6 +28,7 @@ Card { height:parent.height leftPadding: 12 rightPadding: 12 + font.pixelSize: 14 wrapMode: Text.WordWrap } } diff --git a/qml/ui/elements/WorkaroundMessageBox.qml b/qml/ui/elements/WorkaroundMessageBox.qml index 54063cb21..780dc27c0 100644 --- a/qml/ui/elements/WorkaroundMessageBox.qml +++ b/qml/ui/elements/WorkaroundMessageBox.qml @@ -35,6 +35,7 @@ Card { text: _messageBoxInstance.text leftPadding: 12 rightPadding: 12 + font.pixelSize: 14 wrapMode: Text.WordWrap } } diff --git a/qml/ui/widgets/WBLinkRateControlWidget.qml b/qml/ui/widgets/WBLinkRateControlWidget.qml index e9ca37931..9ee17494f 100644 --- a/qml/ui/widgets/WBLinkRateControlWidget.qml +++ b/qml/ui/widgets/WBLinkRateControlWidget.qml @@ -276,6 +276,27 @@ Make the video more stable (less microfreezes) on the cost of less image quality onCheckedChanged: settings.wb_link_rate_control_widget_show_fec_and_keyframe = checked } } + Item { + width: parent.width + height: 32 + Text { + text: qsTr("Show throttle warning") + color: "white" + height: parent.height + font.bold: true + font.pixelSize: detailPanelFontPixels; + anchors.left: parent.left + verticalAlignment: Text.AlignVCenter + } + Switch { + width: 32 + height: parent.height + anchors.rightMargin: 6 + anchors.right: parent.right + checked: settings.wb_link_rate_control_widget_show_throttle_warning + onCheckedChanged: settings.wb_link_rate_control_widget_show_throttle_warning = checked + } + } Item { @@ -433,20 +454,17 @@ Make the video more stable (less microfreezes) on the cost of less image quality anchors.fill: parent scale: bw_current_scale - Item { - anchors.fill: parent - anchors.centerIn: parent + Column { + anchors.top: widgetInner.top + width: parent.width Text { id: channelText y: 0 width: parent.width - height: parent.height / 3 color: settings.color_text text: get_text_channel() - anchors.top: parent.top - anchors.bottomMargin: 0 - verticalAlignment: Text.AlignBottom + verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pixelSize: 14 font.family: settings.font_text @@ -454,7 +472,6 @@ Make the video more stable (less microfreezes) on the cost of less image quality styleColor: settings.color_glow visible: settings.wb_link_rate_control_widget_show_frequency } - Text { id: mcsText y: 0 @@ -462,9 +479,7 @@ Make the video more stable (less microfreezes) on the cost of less image quality height: 14 color: settings.color_text text: get_text_bitrate() - anchors.top: channelText.bottom - anchors.bottomMargin: 0 - verticalAlignment: Text.AlignBottom + verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pixelSize: 14 font.family: settings.font_text @@ -473,16 +488,13 @@ Make the video more stable (less microfreezes) on the cost of less image quality visible: settings.wb_link_rate_control_widget_show_bitrate } Text { + id: fec_keyfra y: 0 width: parent.width height: 14 color: settings.color_text text: get_text_fec_keyframe() - //anchors.bottom: parent.bottom - //anchors.bottomMargin: 0 - anchors.left: parent.left - anchors.top: mcsText.bottom - verticalAlignment: Text.AlignBottom + verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pixelSize: 14 font.family: settings.font_text @@ -490,6 +502,24 @@ Make the video more stable (less microfreezes) on the cost of less image quality styleColor: settings.color_glow visible: settings.wb_link_rate_control_widget_show_fec_and_keyframe } + Text{ + width: parent.width + height: 14 + color: settings.color_warn + font.pixelSize: 14 + font.family: settings.font_text + style: Text.Outline + styleColor: settings.color_glow + visible: settings.wb_link_rate_control_widget_show_throttle_warning + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: { + if(_ohdSystemAir.is_alive && _ohdSystemAir.curr_n_rate_adjustments>0){ + return "THROTTLED"; + } + return ""; + } + } } }