Commit a8154e23 authored by Gus Grubba's avatar Gus Grubba

Video Stream Control Widget

parent aeb0e8a7
......@@ -179,6 +179,7 @@
<file alias="VehicleSummary.qml">src/VehicleSetup/VehicleSummary.qml</file>
<file alias="VirtualJoystick.qml">src/FlightDisplay/VirtualJoystick.qml</file>
<file alias="CameraPageWidget.qml">src/FlightMap/Widgets/CameraPageWidget.qml</file>
<file alias="VideoPageWidget.qml">src/FlightMap/Widgets/VideoPageWidget.qml</file>
<file alias="ValuePageWidget.qml">src/FlightMap/Widgets/ValuePageWidget.qml</file>
<file alias="HealthPageWidget.qml">src/FlightMap/Widgets/HealthPageWidget.qml</file>
<file alias="VibrationPageWidget.qml">src/FlightMap/Widgets/VibrationPageWidget.qml</file>
......
......@@ -43,8 +43,6 @@ QGCView {
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _videoReceiver: QGroundControl.videoManager.videoReceiver
property bool _recordingVideo: _videoReceiver && _videoReceiver.recording
property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true
property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
property real _savedZoomLevel: 0
......@@ -346,63 +344,6 @@ QGCView {
property var qgcView: root
}
// Button to start/stop video recording
Item {
z: _flightVideoPipControl.z + 1
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
anchors.bottom: _flightVideo.bottom
anchors.right: _flightVideo.right
height: ScreenTools.defaultFontPixelHeight * 2
width: height
visible: _videoReceiver && _videoReceiver.videoRunning && QGroundControl.settingsManager.videoSettings.showRecControl.rawValue && _flightVideo.visible && !_isCamera && !QGroundControl.videoManager.fullScreen
opacity: 0.75
readonly property string recordBtnBackground: "BackgroundName"
Rectangle {
id: recordBtnBackground
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
radius: _recordingVideo ? 0 : height
color: "red"
SequentialAnimation on visible {
running: _recordingVideo
loops: Animation.Infinite
PropertyAnimation { to: false; duration: 1000 }
PropertyAnimation { to: true; duration: 1000 }
}
}
QGCColoredImage {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: height * 0.625
sourceSize.width: width
source: "/qmlimages/CameraIcon.svg"
visible: recordBtnBackground.visible
fillMode: Image.PreserveAspectFit
color: "white"
}
MouseArea {
anchors.fill: parent
onClicked: {
if (_videoReceiver) {
if (_recordingVideo) {
_videoReceiver.stopRecording()
// reset blinking animation
recordBtnBackground.visible = true
} else {
_videoReceiver.startRecording()
}
}
}
}
}
MultiVehicleList {
anchors.margins: _margins
anchors.top: singleMultiSelector.bottom
......
......@@ -34,7 +34,7 @@ Item {
color: Qt.rgba(0,0,0,0.75)
visible: !(_videoReceiver && _videoReceiver.videoRunning)
QGCLabel {
text: qsTr("WAITING FOR VIDEO")
text: _videoReceiver && _videoReceiver.enabled ? qsTr("WAITING FOR VIDEO") : qsTr("VIDEO DISABLED")
font.family: ScreenTools.demiboldFontFamily
color: "white"
font.pointSize: _mainIsMap ? ScreenTools.smallFontPointSize : ScreenTools.largeFontPointSize
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.4
import QtPositioning 5.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
/// Video streaming page for Instrument Panel PageView
Item {
width: pageWidth
height: videoGrid.height + (ScreenTools.defaultFontPixelHeight * 2)
anchors.margins: ScreenTools.defaultFontPixelWidth * 2
anchors.centerIn: parent
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _communicationLost: _activeVehicle ? _activeVehicle.connectionLost : false
property var _videoReceiver: QGroundControl.videoManager.videoReceiver
property bool _recordingVideo: _videoReceiver && _videoReceiver.recording
property bool _videoRunning: _videoReceiver && _videoReceiver.videoRunning
QGCPalette { id:qgcPal; colorGroupEnabled: parent.enabled }
GridLayout {
id: videoGrid
columns: 2
columnSpacing: ScreenTools.defaultFontPixelWidth * 2
rowSpacing: ScreenTools.defaultFontPixelHeight
anchors.centerIn: parent
QGCLabel {
text: qsTr("Enable Stream")
font.pointSize: ScreenTools.smallFontPointSize
}
Switch {
checked: _videoRunning
enabled: _activeVehicle
onClicked: {
if(checked) {
_videoReceiver.start()
} else {
_videoReceiver.stop()
}
}
style: SwitchStyle {
groove: Rectangle {
implicitWidth: ScreenTools.defaultFontPixelWidth * 6
implicitHeight: ScreenTools.defaultFontPixelHeight
color: control.checked ? qgcPal.colorGreen : qgcPal.colorGrey
radius: 3
border.color: qgcPal.button
border.width: 1
}
}
}
QGCLabel {
text: qsTr("Stream Recording")
font.pointSize: ScreenTools.smallFontPointSize
visible: QGroundControl.settingsManager.videoSettings.showRecControl.rawValue
}
// Button to start/stop video recording
Item {
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
height: ScreenTools.defaultFontPixelHeight * 2
width: height
Layout.alignment: Qt.AlignHCenter
visible: QGroundControl.settingsManager.videoSettings.showRecControl.rawValue
Rectangle {
id: recordBtnBackground
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
radius: _recordingVideo ? 0 : height
color: _videoRunning ? "red" : "gray"
SequentialAnimation on opacity {
running: _recordingVideo
loops: Animation.Infinite
PropertyAnimation { to: 0.5; duration: 500 }
PropertyAnimation { to: 1.0; duration: 500 }
}
}
QGCColoredImage {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: height * 0.625
sourceSize.width: width
source: "/qmlimages/CameraIcon.svg"
visible: recordBtnBackground.visible
fillMode: Image.PreserveAspectFit
color: "white"
}
MouseArea {
anchors.fill: parent
enabled: _videoRunning
onClicked: {
if (_recordingVideo) {
_videoReceiver.stopRecording()
// reset blinking animation
recordBtnBackground.opacity = 1
} else {
_videoReceiver.startRecording()
}
}
}
}
}
}
......@@ -38,7 +38,7 @@ Rectangle {
width: parent.height -(_margins * 2)
sourceSize.width: width
fillMode: Image.PreserveAspectFit
visible: pageWidgetLoader.item.showSettingsIcon
visible: pageWidgetLoader.item ? (pageWidgetLoader.item.showSettingsIcon ? pageWidgetLoader.item.showSettingsIcon : false) : false
QGCMouseArea {
fillItem: parent
......
......@@ -67,6 +67,7 @@ VideoReceiver::VideoReceiver(QObject* parent)
, _videoSurface(NULL)
, _videoRunning(false)
, _showFullScreen(false)
, _enabled(true)
{
_videoSurface = new VideoSurface;
#if defined(QGC_GST_STREAMING)
......@@ -147,8 +148,10 @@ VideoReceiver::_connected()
_timer.stop();
_socket->deleteLater();
_socket = NULL;
_serverPresent = true;
start();
if(_enabled) {
_serverPresent = true;
start();
}
}
#endif
......@@ -161,7 +164,9 @@ VideoReceiver::_socketError(QAbstractSocket::SocketError socketError)
_socket->deleteLater();
_socket = NULL;
//-- Try again in 5 seconds
_timer.start(5000);
if(_enabled) {
_timer.start(5000);
}
}
#endif
......@@ -175,18 +180,19 @@ VideoReceiver::_timeout()
delete _socket;
_socket = NULL;
}
//-- RTSP will try to connect to the server. If it cannot connect,
// it will simply give up and never try again. Instead, we keep
// attempting a connection on this timer. Once a connection is
// found to be working, only then we actually start the stream.
QUrl url(_uri);
_socket = new QTcpSocket;
_socket->setProxy(QNetworkProxy::NoProxy);
connect(_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), this, &VideoReceiver::_socketError);
connect(_socket, &QTcpSocket::connected, this, &VideoReceiver::_connected);
//qCDebug(VideoReceiverLog) << "Trying to connect to:" << url.host() << url.port();
_socket->connectToHost(url.host(), url.port());
_timer.start(5000);
if(_enabled) {
//-- RTSP will try to connect to the server. If it cannot connect,
// it will simply give up and never try again. Instead, we keep
// attempting a connection on this timer. Once a connection is
// found to be working, only then we actually start the stream.
QUrl url(_uri);
_socket = new QTcpSocket;
_socket->setProxy(QNetworkProxy::NoProxy);
connect(_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), this, &VideoReceiver::_socketError);
connect(_socket, &QTcpSocket::connected, this, &VideoReceiver::_connected);
_socket->connectToHost(url.host(), url.port());
_timer.start(5000);
}
}
#endif
......@@ -203,6 +209,8 @@ VideoReceiver::_timeout()
void
VideoReceiver::start()
{
_enabled = true;
emit enabledChanged();
#if defined(QGC_GST_STREAMING)
qCDebug(VideoReceiverLog) << "start()";
......@@ -416,6 +424,8 @@ VideoReceiver::start()
void
VideoReceiver::stop()
{
_enabled = false;
emit enabledChanged();
#if defined(QGC_GST_STREAMING)
qCDebug(VideoReceiverLog) << "stop()";
if(!_streaming) {
......@@ -814,7 +824,7 @@ VideoReceiver::_updateTimer()
stop();
}
} else {
if(!running() && !_uri.isEmpty()) {
if(!running() && !_uri.isEmpty() && _enabled) {
start();
}
}
......
......@@ -38,9 +38,10 @@ public:
Q_PROPERTY(bool recording READ recording NOTIFY recordingChanged)
#endif
Q_PROPERTY(VideoSurface* videoSurface READ videoSurface CONSTANT)
Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged)
Q_PROPERTY(QString imageFile READ imageFile NOTIFY imageFileChanged)
Q_PROPERTY(bool showFullScreen READ showFullScreen WRITE setShowFullScreen NOTIFY showFullScreenChanged)
Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged)
Q_PROPERTY(QString imageFile READ imageFile NOTIFY imageFileChanged)
Q_PROPERTY(bool showFullScreen READ showFullScreen WRITE setShowFullScreen NOTIFY showFullScreenChanged)
Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
explicit VideoReceiver(QObject* parent = 0);
~VideoReceiver();
......@@ -57,6 +58,8 @@ public:
bool videoRunning () { return _videoRunning; }
QString imageFile () { return _imageFile; }
bool showFullScreen () { return _showFullScreen; }
bool enabled () { return _enabled; }
void grabImage (QString imageFile);
void setShowFullScreen (bool show) { _showFullScreen = show; emit showFullScreenChanged(); }
......@@ -65,6 +68,7 @@ signals:
void videoRunningChanged ();
void imageFileChanged ();
void showFullScreenChanged ();
void enabledChanged ();
#if defined(QGC_GST_STREAMING)
void recordingChanged ();
void msgErrorReceived ();
......@@ -136,6 +140,7 @@ private:
VideoSurface* _videoSurface;
bool _videoRunning;
bool _showFullScreen;
bool _enabled;
};
......
......@@ -39,6 +39,7 @@ public:
, defaultOptions (NULL)
, valuesPageWidgetInfo (NULL)
, cameraPageWidgetInfo (NULL)
, videoPageWidgetInfo (NULL)
, healthPageWidgetInfo (NULL)
, vibrationPageWidgetInfo (NULL)
{
......@@ -80,6 +81,7 @@ public:
QmlComponentInfo* valuesPageWidgetInfo;
QmlComponentInfo* cameraPageWidgetInfo;
QmlComponentInfo* videoPageWidgetInfo;
QmlComponentInfo* healthPageWidgetInfo;
QmlComponentInfo* vibrationPageWidgetInfo;
QVariantList instrumentPageWidgetList;
......@@ -148,13 +150,19 @@ QVariantList &QGCCorePlugin::settingsPages()
QVariantList& QGCCorePlugin::instrumentPages(void)
{
if (!_p->valuesPageWidgetInfo) {
_p->valuesPageWidgetInfo = new QmlComponentInfo(tr("Values"), QUrl::fromUserInput("qrc:/qml/ValuePageWidget.qml"));
_p->cameraPageWidgetInfo = new QmlComponentInfo(tr("Camera"), QUrl::fromUserInput("qrc:/qml/CameraPageWidget.qml"));
_p->healthPageWidgetInfo = new QmlComponentInfo(tr("Health"), QUrl::fromUserInput("qrc:/qml/HealthPageWidget.qml"));
_p->valuesPageWidgetInfo = new QmlComponentInfo(tr("Values"), QUrl::fromUserInput("qrc:/qml/ValuePageWidget.qml"));
_p->cameraPageWidgetInfo = new QmlComponentInfo(tr("Camera"), QUrl::fromUserInput("qrc:/qml/CameraPageWidget.qml"));
#if defined(QGC_GST_STREAMING)
_p->videoPageWidgetInfo = new QmlComponentInfo(tr("Video"), QUrl::fromUserInput("qrc:/qml/VideoPageWidget.qml"));
#endif
_p->healthPageWidgetInfo = new QmlComponentInfo(tr("Health"), QUrl::fromUserInput("qrc:/qml/HealthPageWidget.qml"));
_p->vibrationPageWidgetInfo = new QmlComponentInfo(tr("Vibration"), QUrl::fromUserInput("qrc:/qml/VibrationPageWidget.qml"));
_p->instrumentPageWidgetList.append(QVariant::fromValue(_p->valuesPageWidgetInfo));
_p->instrumentPageWidgetList.append(QVariant::fromValue(_p->cameraPageWidgetInfo));
#if defined(QGC_GST_STREAMING)
_p->instrumentPageWidgetList.append(QVariant::fromValue(_p->videoPageWidgetInfo));
#endif
_p->instrumentPageWidgetList.append(QVariant::fromValue(_p->healthPageWidgetInfo));
_p->instrumentPageWidgetList.append(QVariant::fromValue(_p->vibrationPageWidgetInfo));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment