aboutsummaryrefslogtreecommitdiffstats
path: root/qml/Viper
diff options
context:
space:
mode:
Diffstat (limited to 'qml/Viper')
-rwxr-xr-xqml/Viper/Button.qml89
-rwxr-xr-xqml/Viper/ControlPanel.qml461
-rwxr-xr-xqml/Viper/DelegateItem.qml65
-rwxr-xr-xqml/Viper/GraphPanel.qml267
-rwxr-xr-xqml/Viper/OpenMpd.qml113
-rwxr-xr-xqml/Viper/OptionConnections.qml673
-rwxr-xr-xqml/Viper/Options.qml1710
-rwxr-xr-xqml/Viper/ProgressBar.qml124
-rwxr-xr-xqml/Viper/Slider.qml117
-rwxr-xr-xqml/Viper/VideoCodec.qml150
-rwxr-xr-xqml/Viper/main.qml945
-rwxr-xr-xqml/Viper/utils.js100
12 files changed, 4814 insertions, 0 deletions
diff --git a/qml/Viper/Button.qml b/qml/Viper/Button.qml
new file mode 100755
index 00000000..7af64c5f
--- /dev/null
+++ b/qml/Viper/Button.qml
@@ -0,0 +1,89 @@
+/******************************************************************************
+ Copyright (C) 2013-2016 Wang Bin <wbsecg1@gmail.com>
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ property string text
+ property url icon
+ property alias iconChecked: iconChecked.source
+ property bool checkable: false
+ property bool checked: false
+ property color bgColor: "#555555"
+ property color bgColorSelected: "#ee6666dd"
+ property color textColor: "white"
+ property bool hovered: false //mouseArea.containsMouse
+ readonly property alias pressed: mouseArea.pressed
+ signal clicked()
+ signal pressAndHold()
+
+ opacity: 0.7
+ color: checked ? bgColorSelected : mouseArea.pressed ? Qt.darker(bgColor) : bgColor
+ border.color: Qt.lighter(color)
+
+ Text {
+ id: text
+ anchors.fill: parent
+ text: root.text
+ font.pixelSize: 0.5 * parent.height
+ color: textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ Image {
+ source: icon
+ anchors.fill: parent
+ visible: !checked
+ }
+ Image {
+ id: iconChecked
+ anchors.fill: parent
+ visible: checked
+ }
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: {
+ if (root.checkable)
+ root.checked = !root.checked
+ root.clicked()
+ }
+ onHoveredChanged: {
+ if (mouseX > 65535) //qt5.6 touch screen release finger becomes very large e.g. 0x7fffffff
+ return
+ hovered = mouseArea.containsMouse
+ }
+ onPressAndHold: root.pressAndHold()
+ }
+ states: [
+ State {
+ name: "brighter"
+ when: hovered // only the first true State is applied, so put scale and opacity together
+ PropertyChanges { target: root; opacity: 1.0; scale: mouseArea.pressed ? 1.06 : 1.0 }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"; to: "*"
+ PropertyAnimation {
+ properties: "opacity,scale"
+ easing.type: Easing.OutQuart
+ duration: 300
+ }
+ }
+ ]
+}
diff --git a/qml/Viper/ControlPanel.qml b/qml/Viper/ControlPanel.qml
new file mode 100755
index 00000000..4f5848d7
--- /dev/null
+++ b/qml/Viper/ControlPanel.qml
@@ -0,0 +1,461 @@
+/******************************************************************************
+ QtAV: Multimedia framework based on Qt and FFmpeg
+ Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
+* This file is part of QtAV (from 2013)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+import "utils.js" as Utils
+import QtQuick.Window 2.1
+import QtAV 1.4
+
+Rectangle {
+ id: root
+ function scaled(x) {
+ console.log("Screen " + screenPixelDensity + "; r: " + Screen.pixelDensity/Screen.logicalPixelDensity + "; size: " + Screen.width + "x" + Screen.height);
+ console.log("screen density logical: " + Screen.logicalPixelDensity + " pixel: " + Screen.pixelDensity + "; " + x + ">>>" +x*Screen.pixelDensity/Screen.logicalPixelDensity);
+ return x*Screen.pixelDensity/Screen.logicalPixelDensity;
+ }
+
+ color: "black"
+ opacity: 0.9
+ radius: Utils.scaled(10)
+ height: Utils.scaled(80)
+ width: itemWidth-25*pixDens
+
+ property string playState: "stop"
+ property int duration: 0
+ property real volume: 1
+ property bool mute: false
+ property bool hiding: false
+ signal startGraph
+ signal pauseGraph
+ signal stopGraph
+ signal resizeWindowFullScreen
+ signal resizeWindow
+ signal openMpd
+ signal openOptions
+ signal openOptionConnections
+ signal openGraph
+ signal hideGraph
+ signal repeatVideo
+ signal donotRepeatVideo
+ signal saveFullScreen
+ signal saveExitFullScreen
+ signal togglePause
+ signal showInfo
+ signal showHelp
+ signal openFile
+ signal openUrl
+ signal downloadMPD
+
+ function setPlayingProgress(value)
+ {
+ playState = "play"
+ }
+
+ function setStopState()
+ {
+ isPlaying = "stop"
+ playBtn.checked = false
+
+ }
+
+ function setPlayingState() {
+ playBtn.checked = true
+ playState = "play"
+
+ }
+
+ function setPauseState() {
+ playBtn.checked = false
+ playState = "pause"
+ }
+
+ function toggleFullScreen() {
+ fullScreenBtn.checked = !fullScreenBtn.checked
+ }
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#88445566" }
+ GradientStop { position: 0.618; color: "#cc1a2b3a" }
+ GradientStop { position: 1.0; color: "#ee000000" }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ onHoveredChanged: {
+ if (containsMouse) {
+ if (timer.running) //timer may ran a few seconds(<3) ago
+ timer.stop();
+ root.aniShow()
+ } else {
+
+ }
+ }
+
+ onPressed: {
+ if (timer.running) //timer may ran a few seconds(<3) ago
+ timer.stop();
+ root.aniShow()
+ }
+ }
+
+ ProgressBar {
+ id: progress
+ objectName: "progress"
+
+ anchors {
+ top: parent.top
+ topMargin: Utils.scaled(8)
+ left: parent.left
+ leftMargin: Utils.scaled(20)
+ right: parent.right
+ rightMargin: Utils.scaled(20)
+ }
+ height: Utils.scaled(8)
+ onValueChangedByUi: {
+ dashPlayer.seekVideo(value);
+ }
+
+ onEnter: {
+ if (playState == "stop")
+ return
+ }
+
+ onLeave: {
+ if (playState == "stop")
+ return
+ }
+ onHoverAt: {
+ if (playState == "stop")
+ return;
+ }
+ }
+
+ Item {
+ layer.enabled: true
+ anchors {
+ top: progress.bottom
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ margins: Utils.scaled(8)
+ }
+
+ Text {
+ id: now
+ objectName: "now"
+ text: "00:00:00"//Utils.msec2string(progress.value*duration)
+ anchors {
+ top: parent.top
+ topMargin: Utils.scaled(2)
+ left: parent.left
+ }
+ color: "white"
+ font {
+ pixelSize: Utils.scaled(12) //or point size?
+ }
+ }
+ Text {
+ id: life
+ objectName: "life"
+ text: "00:00:00"//Utils.msec2string(duration)
+ anchors {
+ top: parent.top
+ topMargin: Utils.scaled(2)
+ right: parent.right
+ }
+ color: "white"
+ font {
+ pixelSize: Utils.scaled(12)
+ }
+ }
+ Button {
+ id: playBtn
+ enabled: true
+ objectName: "playBtn"
+ anchors.centerIn: parent
+ checkable: true
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ width: Utils.scaled(50)
+ height: Utils.scaled(50)
+ icon: "qrc:///qml/images/play.svg"
+ iconChecked: "qrc:///qml/images/pause.svg"
+
+ onClicked: {
+ if (checked === true) {
+ console.log(adaptationLogic)
+ console.log(lastPlayed)
+ dashPlayer.downloadMPD(lastPlayed, adaptationLogic, icn)
+ } else {
+ dashPlayer.pause();
+ }
+ }
+ }
+
+ Button {
+ id: stopBtn
+ enabled: true
+ anchors.verticalCenter: playBtn.verticalCenter
+ anchors.right: playBtn.left
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ width: Utils.scaled(35)
+ height: Utils.scaled(35)
+ icon: "qrc:///qml/images/stop.svg"
+ onClicked: {
+ playBtn.checked = false
+ isPlaying = false
+ canBuffer = false
+ dashPlayer.onStopButtonPressed()
+ }
+ }
+
+ Button {
+ id: fullScreenBtn
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(60)
+ anchors.verticalCenter: parent.verticalCenter
+ checkable: true
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ width: Utils.scaled(30)
+ height: Utils.scaled(30)
+ icon: "qrc:///qml/images/fullscreen.png"
+ iconChecked: "qrc:///qml/images/fullscreen-selected.png"
+ visible: (Qt.platform.os != "android")
+ checked: enabledFullScreen
+ onCheckedChanged: {
+ if (checked) {
+ fullScreen()
+ saveFullScreen()
+ } else {
+ exitFullScreen()
+ saveExitFullScreen()
+ }
+ }
+ }
+
+ Row {
+ anchors.right: parent.right
+ anchors.rightMargin: Utils.scaled(70)
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: Utils.scaled(20)
+
+ Button {
+ id: graphBtn
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ checkable: true
+ width: Utils.scaled(30)
+ height: Utils.scaled(30)
+ icon: "qrc:///qml/images/graph.png"
+ iconChecked: "qrc:///qml/images/graph-selected.png"
+ visible: true
+ checked: graph
+ onCheckedChanged: {
+ if ( !graphBtn.checked) {
+ hideGraph()
+ } else {
+ openGraph()
+ }
+ }
+ }
+
+ Button {
+ id: optionsBtn
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ checkable: true
+ width: Utils.scaled(30)
+ height: Utils.scaled(30)
+ icon: "qrc:///qml/images/options.png"
+ iconChecked: "qrc:///qml/images/options-selected.png"
+ visible: true
+ onCheckedChanged: {
+ if (checked)
+ openOptions()
+ }
+ }
+
+ Button {
+ id: optionConnectionsBtn
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ checkable: true
+ width: Utils.scaled(30)
+ height: Utils.scaled(30)
+ icon: "qrc:///qml/images/option-connections.png"
+ iconChecked: "qrc:///qml/images/option-connections-selected.png"
+ visible: true
+ onCheckedChanged: {
+
+ if (checked)
+ openOptionConnections()
+ }
+ }
+
+ Button {
+ id: openBtn
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ checkable: true
+ width: Utils.scaled(30)
+ height: Utils.scaled(30)
+ icon: "qrc:///qml/images/open.png"
+ iconChecked: "qrc:///qml/images/open-selected.png"
+ onCheckedChanged: {
+ if(checked)
+ openMpd()
+ }
+ }
+ Button {
+ id: repeatBtn
+ bgColor: "transparent"
+ bgColorSelected: "transparent"
+ checkable: true
+ width: Utils.scaled(30)
+ height: Utils.scaled(30)
+ icon: "qrc:///qml/images/repeat.png"
+ iconChecked: "qrc:///qml/images/repeat-selected.png"
+ checked: repeat
+ onCheckedChanged: {
+ if ( !repeatBtn.checked) {
+ donotRepeatVideo()
+ } else {
+ repeatVideo()
+ }
+
+ }
+
+ }
+ }
+ }
+
+ Timer {
+ id: timer
+ interval: 3000
+ onTriggered: {
+ root.aniHide()
+ }
+ }
+
+ function hideIfTimedout()
+ {
+ timer.start()
+ }
+
+ PropertyAnimation {
+ id: anim
+ target: root
+ properties: "opacity"
+ function reverse()
+ {
+ duration = 1500
+ to = 0
+ from = root.opacity
+ }
+
+ function reset()
+ {
+ duration = 200
+ from = root.opacity
+ to = 0.9
+ }
+ }
+
+ function aniShow()
+ {
+ hiding = false
+ anim.stop()
+ anim.reset()
+ anim.start()
+ }
+
+ function aniHide()
+ {
+ hiding = true
+ anim.stop()
+ anim.reverse()
+ anim.start()
+ }
+
+ function toggleVisible()
+ {
+ if (hiding)
+ aniShow()
+ else
+ aniHide()
+ }
+
+ function enable()
+ {
+ playBtn.enabled = true
+ stopBtn.enabled = true
+ }
+
+ function disable()
+ {
+ playBtn.enabled = false
+ stopBtn.enabled = false
+ }
+
+
+ function fullScreen()
+ {
+ requestFullScreen()
+ resizeWindowFullScreen()
+ }
+
+ function exitFullScreen()
+ {
+ requestNormalSize()
+ resizeWindow()
+ }
+
+ function checkRepeatButton()
+ {
+ repeatBtn.checked = !repeatBtn.checked;
+ }
+
+ function uncheckOpenBtn()
+ {
+ openBtn.checked = false;
+ }
+
+ function enableOpenBtn()
+ {
+ openBtn.enabled = true;
+ }
+
+ function uncheckOptionsBtn()
+ {
+
+ optionsBtn.checked = false;
+ }
+
+ function uncheckOptionConnectionsBtn()
+ {
+
+ optionConnectionsBtn.checked = false;
+ }
+
+ function enableOptionsBtn()
+ {
+ optionsBtn.enabled = true;
+ }
+}
diff --git a/qml/Viper/DelegateItem.qml b/qml/Viper/DelegateItem.qml
new file mode 100755
index 00000000..edc45572
--- /dev/null
+++ b/qml/Viper/DelegateItem.qml
@@ -0,0 +1,65 @@
+/******************************************************************************
+ QtAV: Multimedia framework based on Qt and FFmpeg
+ Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
+* This file is part of QtAV (from 2013)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+import "utils.js" as Utils
+
+Rectangle {
+ id: root
+ width: Math.max(Utils.kItemWidth, itemText.contentWidth+8)
+ height: itemText.contentWidth
+ property color selectedColor: "#66ddaadd"
+ property alias text: itemText.text
+ color: "#99000000"
+ signal clicked
+ Text {
+ id: itemText
+ color: "white"
+ anchors.fill: parent
+ anchors.margins: 4
+ font.pixelSize: Utils.kFontSize
+ anchors.centerIn: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ root.state = "selected"
+ root.clicked()
+ }
+ }
+ states: [
+ State {
+ name: "selected"
+ PropertyChanges {
+ target: delegateItem
+ color: selectedColor
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"; to: "*"
+ ColorAnimation {
+ properties: "color"
+ easing.type: Easing.OutQuart
+ duration: 500
+ }
+ }
+ ]
+}
diff --git a/qml/Viper/GraphPanel.qml b/qml/Viper/GraphPanel.qml
new file mode 100755
index 00000000..24105225
--- /dev/null
+++ b/qml/Viper/GraphPanel.qml
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.0
+import QtCharts 2.1
+
+
+Rectangle {
+ id: root
+ anchors.fill: parent;
+ color: Qt.rgba(0,0,0,0.5)
+ ChartView {
+ anchors.bottomMargin: parent.height/2
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: windowWidth*0.015
+
+ id: chartViewBitRateFps
+ opacity: 1
+ animationOptions: ChartView.NoAnimation
+ backgroundColor: "transparent"
+ legend.visible: true
+ legend.labelColor: "white"
+ legend.font:Qt.font({pointSize: windowWidth*0.015, bold:true})
+ antialiasing: enabled;
+ property bool openGL: true
+ onOpenGLChanged: {
+ series("signal 1").useOpenGL = openGL;
+ }
+
+ ValueAxis {
+ labelFormat: "%d%"
+ id: bitBufferLevelY
+ labelsColor: "white"
+
+ labelsFont:Qt.font({pointSize: windowWidth*0.015, bold:true})
+ min: 0
+ max: 100
+
+ }
+ ValueAxis {
+ labelFormat: "%d"
+ id: bitRateAxisY
+ labelsColor: "white"
+
+ labelsFont:Qt.font({pointSize: windowWidth*0.015, bold:true})
+ min: 0
+ max: 20
+
+ }
+
+ ValueAxis {
+ labelsVisible: false
+ labelFormat: "%d"
+ labelsAngle: 90
+ labelsFont:Qt.font({pointSize: 1})
+ id: axisX
+ gridVisible: true
+ min: -100
+ max: 0
+ }
+
+ CategoryAxis {
+ id: axesYQualityVideo
+ min: 1
+ max: 19
+ gridVisible: false
+ tickCount: 6
+ labelsColor: "white"
+ labelsFont:Qt.font({pointSize: windowWidth*0.015, bold:true})
+ CategoryRange {
+ label: "LD"
+ endValue: 4
+ }
+
+ CategoryRange {
+ label: "SD"
+ endValue: 7
+ }
+
+ CategoryRange {
+ label: "HD"
+ endValue: 10
+ }
+
+ CategoryRange {
+ label: "FHD"
+ endValue: 13
+ }
+
+ CategoryRange {
+ label: "QHD"
+ endValue: 16
+ }
+
+ CategoryRange {
+ label: "UHD"
+ endValue: 19
+ }
+ }
+
+ LineSeries {
+ id: bufferLevelSeries
+ name: "Buffer Level (%)"
+ axisX: axisX
+ color: "green"
+ width: pixDens*3
+ axisY: bitBufferLevelY
+ useOpenGL: chartViewBitRateFps.openGL
+ }
+
+ LineSeries {
+ id: bitRateSeries
+ name: "Download Quality"
+ axisX: axisX
+ color: "yellow"
+ width: pixDens*3
+ axisYRight: axesYQualityVideo
+ useOpenGL: chartViewBitRateFps.openGL
+ }
+ }
+
+ ChartView {
+ anchors.topMargin: parent.height/2
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: windowWidth*0.048
+ id: chartViewQuality
+ opacity: 1
+ animationOptions: ChartView.NoAnimation
+ backgroundColor: "transparent"
+ legend.visible: true
+ legend.labelColor: "white"
+ legend.font:Qt.font({pointSize: windowWidth*0.015, bold:true})
+
+ antialiasing: enabled;
+ property bool openGL: true
+ onOpenGLChanged: {
+ series("signal 1").useOpenGL = openGL;
+ }
+
+ ValueAxis {
+ labelsVisible: false
+ labelFormat: "%d"
+ labelsAngle: 90
+ labelsFont:Qt.font({pointSize: 1})
+ id: axisX2
+ gridVisible: true
+ min: -100
+ max: 0
+ }
+
+ ValueAxis {
+ labelFormat: "%d"
+ id: bitRateAxisY2
+ gridVisible: false
+ labelsColor: "white"
+ labelsFont:Qt.font({pointSize: windowWidth*0.015, bold:true})
+ min: 0
+ max: 20
+ }
+
+ LineSeries {
+ id: dummySeries
+ visible: false
+ axisX: axisX2
+ axisY: bitRateAxisY2
+ }
+
+ CategoryAxis {
+ id: axeYQuality
+ min: 1
+ max: 19
+ tickCount: 6
+ labelsColor: "white"
+ labelsFont:Qt.font({pointSize: windowWidth*0.015, bold:true})
+ CategoryRange {
+ label: "LD"
+ endValue: 4
+ }
+ CategoryRange {
+ label: "SD"
+ endValue: 7
+ }
+ CategoryRange {
+ label: "HD"
+ endValue: 10
+ }
+
+ CategoryRange {
+ label: "FHD"
+ endValue: 13
+ }
+
+ CategoryRange {
+ label: "QHD"
+ endValue: 16
+ }
+ CategoryRange {
+ label: "UHD"
+ endValue: 19
+ }
+ }
+
+ LineSeries {
+ id: qualitySeries
+ name: "Displayed Quality (Mbps)"
+ axisX: axisX2
+ width: pixDens*3
+ color: "white"
+ axisYRight: axeYQuality
+
+ useOpenGL: chartViewQuality.openGL
+ }
+ }
+
+ Timer {
+ id: refreshTimer
+ interval: 10
+ objectName: "refreshTimer"
+ running: false
+ repeat: true
+ onTriggered: {
+ dataSource.update(bitRateSeries, qualitySeries, bufferLevelSeries);
+ qualitySeries.axisX.min = qualitySeries.at(qualitySeries.count-1).x - 1000
+ qualitySeries.axisX.max = qualitySeries.at(qualitySeries.count-1).x
+ bitRateSeries.axisX.min = bitRateSeries.at(bitRateSeries.count-1).x - 1000
+ bitRateSeries.axisX.max = bitRateSeries.at(bitRateSeries.count-1).x
+ }
+ }
+
+ function startTimer()
+ {
+ refreshTimer.running = true;
+ }
+
+ function pauseTimer()
+ {
+ refreshTimer.running = false;
+ }
+
+ function stopTimer()
+ {
+ refreshTimer.running = false;
+ bitRateSeries.clear();
+ bufferLevelSeries.clear();
+ qualitySeries.clear();
+ dataSource.clearData();
+ }
+}
+
diff --git a/qml/Viper/OpenMpd.qml b/qml/Viper/OpenMpd.qml
new file mode 100755
index 00000000..d821f072
--- /dev/null
+++ b/qml/Viper/OpenMpd.qml
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.5
+import QtQuick.Extras 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls 2.0
+import QtQuick.Layouts 1.3
+import "utils.js" as Utils
+Rectangle {
+ signal closeOpenMpd
+ signal saveAndPlayMpd(string newOpenMpd)
+
+ id: root
+ color: "#88445566"
+
+ opacity: 0
+ radius: Utils.scaled(10)
+ height: Utils.scaled(100)
+ width: Utils.scaled(300)
+ enabled: false;
+ GridLayout {
+ id : grid
+ z: parent.z + 1
+ anchors.fill: parent
+ rows : 2
+ columns : 2
+ anchors.leftMargin: Utils.scaled(12)
+
+ anchors.rightMargin: Utils.scaled(12)
+ anchors.topMargin: Utils.scaled(12)
+ anchors.bottomMargin: Utils.scaled(12)
+ property double colMulti : grid.width / grid.columns
+ property double rowMulti : grid.height / grid.rows
+
+ function prefWidth(item)
+ {
+ return colMulti * item.Layout.columnSpan
+ }
+
+ function prefHeight(item)
+ {
+ return rowMulti * item.Layout.rowSpan
+ }
+
+ ComboBox {
+ z: parent.z + 1
+ id: comboBoxList
+ Layout.rowSpan : 1
+ Layout.columnSpan : 2
+ Layout.preferredWidth : parent.colMulti * 2 + Utils.scaled(5) //grid.prefWidth(this)
+ Layout.preferredHeight : parent.rowMulti//grid.prefHeight(this)
+
+ onCurrentIndexChanged: {
+ }
+
+ model: ListModel {
+ id: mpdItems
+ ListElement { text: "gastown"; }
+ ListElement { text: "sintel"; }
+ }
+ currentIndex: find(lastPlayed)
+ }
+
+ Button {
+ id: cancelBtn
+ z: parent.z + 1
+
+ text: "Cancel"
+ Layout.rowSpan : 1
+ Layout.columnSpan: 1
+ Layout.preferredWidth : grid.prefWidth(this)
+ Layout.preferredHeight : grid.prefHeight(this)
+ onClicked: {
+
+ closeOpenMpd();
+ }
+ }
+
+ Button {
+ id: downloadBtn
+ z: parent.z + 1
+ Layout.rowSpan : 1
+ Layout.columnSpan: 1
+ Layout.preferredWidth : grid.prefWidth(this)
+ Layout.preferredHeight : grid.prefHeight(this)
+ text: "Download"
+ onClicked: {
+ saveAndPlayMpd(mpdItems.get(comboBoxList.currentIndex).text)
+ closeOpenMpd();
+ }
+
+
+ }
+
+
+
+ }
+
+}
+
diff --git a/qml/Viper/OptionConnections.qml b/qml/Viper/OptionConnections.qml
new file mode 100755
index 00000000..daab7e98
--- /dev/null
+++ b/qml/Viper/OptionConnections.qml
@@ -0,0 +1,673 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.5
+import QtQuick.Extras 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls 2.0
+import QtQuick.Layouts 1.3
+import "utils.js" as Utils
+Rectangle {
+ signal closeOptionConnections
+ signal saveAutotune(bool selectedAutotune)
+ signal saveLifetime(int selectedLifetime)
+ signal saveRetransmissions(int selectedRetransmissions)
+ signal saveAlpha(real selectedAlpha)
+ signal saveBeta(real selectedBeta)
+ signal saveDrop(real selectedDrop)
+ signal saveBetaWifi(real selectedBetaWifi)
+ signal saveDropWifi(real selectedDropWifi)
+ signal saveDelayWifi(int selectedDelayWifi)
+ signal saveBetaLte(real selectedBetaLte)
+ signal saveDropLte(real selectedDropLte)
+ signal saveDelayLte(int selectedDelayLte)
+ signal saveBatchingParameter(int selectedBatchingParameter)
+ signal saveRateEstimator(int selectedRateEstimator)
+ property int heightRow: Utils.scaled(60)
+
+ id: root
+ color: "#88445566"
+ property variant target
+ opacity: 0
+ radius: Utils.scaled(10)
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ enabled: false
+
+ Item {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+ id: itemAutotune
+ Label {
+ id: labelAdaptationSetList
+ color: "white"
+ anchors.top: parent.top
+ anchors.right: comboAutotune.left
+ anchors.rightMargin: Utils.scaled(5)
+
+ anchors.topMargin: (comboAutotune.height - height)/2
+ text: "Auto Tune"
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ ComboBox {
+ z: parent.z + 1
+ id: comboAutotune
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ width: Utils.scaled(200)
+ enabled: true
+
+ textRole: "text"
+ model: ListModel {
+ id: adaptationLogicModel
+
+ ListElement { text: "True"; }
+ ListElement { text: "False"; }
+
+ }
+ onCurrentIndexChanged: {
+ console.debug( currentIndex + " " + currentText)
+ }
+ currentIndex: autotune == true ? 0 : 1
+
+ }
+ }
+
+ Item {
+ id: itemLifetime
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+ Label {
+ text: "Lifetime"
+ id: labelLifetime
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxLifetime.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxLifetime.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+ SpinBox {
+ id: spinboxLifetime
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 1
+ value: lifetime
+ to: 10000
+ }
+ }
+
+ Item {
+ id: itemRetransmissions
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+
+ Label {
+ text: "Retransmissions"
+ id: labelRetransmissions
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxRetransmissions.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxRetransmissions.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+ SpinBox {
+ id: spinboxRetransmissions
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 1
+ value: retransmissions
+ to: 10000
+ stepSize: 1
+ }
+ }
+
+ Item {
+ id: itemAlpha
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + 2*heightRow
+
+ Label {
+ text: "Alpha"
+ id: labelAlpha
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxAlpha.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxAlpha.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+ SpinBox {
+ id: spinboxAlpha
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: alpha*100
+ to: 10000
+ stepSize: 1
+ property int decimals: 2
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxAlpha.from, spinboxAlpha.to)
+ top: Math.max(spinboxAlpha.from, spinboxAlpha.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxAlpha.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemBeta
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 2
+
+ Label {
+ text: "Beta"
+ id: labelBeta
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBeta.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBeta.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+ SpinBox {
+ id: spinboxBeta
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: beta*100
+ to: 10000
+ stepSize: 1
+
+ property int decimals: 2
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBeta.from, spinboxBeta.to)
+ top: Math.max(spinboxBeta.from, spinboxBeta.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBeta.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemDrop
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 2
+
+ Label {
+ text: "Drop"
+ id: labelDrop
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxDrop.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxDrop.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxDrop
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(700)
+ from: 0
+ value: drop*1000
+ to: 100000
+ stepSize: 1
+ property int decimals: 3
+ property real realValue: value / 1000
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxDrop.from, spinboxDrop.to)
+ top: Math.max(spinboxDrop.from, spinboxDrop.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 1000).toLocaleString(locale, 'f', spinboxDrop.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 1000
+ }
+ }
+ }
+
+
+ Item {
+ id: itemBetaWifi
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 3
+
+ Label {
+ text: "BetaWifi"
+ id: labelBetaWifi
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBetaWifi.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBetaWifi.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBetaWifi
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: betaWifi*100
+ to: 10000
+ stepSize: 1
+ property int decimals: 2
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBetaWifi.from, spinboxBetaWifi.to)
+ top: Math.max(spinboxBetaWifi.from, spinboxBetaWifi.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBetaWifi.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemDropWifi
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 3
+
+ Label {
+ text: "DropWifi"
+ id: labelDropWifi
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxDropWifi.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxDropWifi.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxDropWifi
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: dropWifi*1000
+ to: 100000
+ stepSize: 1
+ property int decimals: 3
+ property real realValue: value / 1000
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxDropWifi.from, spinboxDropWifi.to)
+ top: Math.max(spinboxDropWifi.from, spinboxDropWifi.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 1000).toLocaleString(locale, 'f', spinboxDropWifi.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 1000
+ }
+ }
+ }
+
+ Item {
+ id: itemDelayWifi
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 3
+
+ Label {
+ text: "DelayWifi"
+ id: labelDelayWifi
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxDelayWifi.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxDelayWifi.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxDelayWifi
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(700)
+ from: 1
+ value: delayWifi
+ to: 100000
+ stepSize: 1
+ }
+ }
+
+ Item {
+ id: itemBetaLte
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 4
+
+ Label {
+ text: "BetaLte"
+ id: labelBetaLte
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBetaLte.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBetaLte.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBetaLte
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: betaLte*100
+ to: 10000
+ stepSize: 1
+ property int decimals: 2
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBetaLte.from, spinboxBetaLte.to)
+ top: Math.max(spinboxBetaLte.from, spinboxBetaLte.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBetaLte.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemDropLte
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 4
+
+ Label {
+ text: "DropLte"
+ id: labelDropLte
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxDropLte.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxDropLte.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxDropLte
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: dropLte*1000
+ to: 100000
+ stepSize: 1
+ property int decimals: 3
+ property real realValue: value / 1000
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxDropLte.from, spinboxDropLte.to)
+ top: Math.max(spinboxDropLte.from, spinboxDropLte.to)
+ }
+
+ textFromValue: function(value, locale) {
+ return Number(value / 1000).toLocaleString(locale, 'f', spinboxDropLte.decimals)
+ }
+
+ valueFromText: function(text, locale) {
+ return Number.fromLocaleString(locale, text) * 1000
+ }
+ }
+ }
+
+ Item {
+ id: itemDelayLte
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 4
+
+ Label {
+ text: "DelayLte"
+ id: labelDelayLte
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxDelayLte.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxDelayLte.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxDelayLte
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(700)
+ from: 1
+ value: delayLte
+ to: 100000
+ stepSize: 1
+ }
+ }
+
+ Item {
+ id: itemBatchingParameter
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 5
+
+ Label {
+ text: "Batching Parameter"
+ id: labelBatchingParameter
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBatchingParameter.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBatchingParameter.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBatchingParameter
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 1
+ value: batchingParameter
+ to: 100000
+ stepSize: 1
+ }
+ }
+
+ Item {
+ id: itemRateEstimator
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow * 5
+
+ Label {
+ text: "Rate Estimator"
+ id: labelRateEstimator
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxRateEstimator.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxRateEstimator.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxRateEstimator
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: rateEstimator
+ to: 1
+ stepSize: 1
+ }
+ }
+
+ Item {
+ id: itemButton
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: Utils.scaled(12)
+ anchors.bottomMargin: Utils.scaled(12)
+
+ Button {
+ id: cancelBtn
+ z: parent.z + 1
+ text: "Cancel"
+ anchors.right: saveBtn.left
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: Utils.scaled(5)
+ onClicked: {
+ closeOptionConnections();
+ }
+ }
+
+ Button {
+ id: saveBtn
+ z: parent.z + 1
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+
+ text: "Save"
+ onClicked: {
+ saveAutotune(comboAutotune.currentIndex == 0 ? true : false)
+ saveLifetime(spinboxLifetime.value)
+ saveRetransmissions(spinboxRetransmissions.value)
+ saveAlpha(spinboxAlpha.value/100)
+ saveBeta(spinboxBeta.value/100)
+ saveDrop(spinboxDrop.value/1000)
+ saveBetaWifi(spinboxBetaWifi.value/100)
+ saveDropWifi(spinboxDropWifi.value/1000)
+ saveDelayWifi(spinboxDelayWifi.value)
+ saveBetaLte(spinboxBetaLte.value/100)
+ saveDropLte(spinboxDropLte.value/1000)
+ saveDelayLte(spinboxDelayLte.value)
+ saveBatchingParameter(spinboxBatchingParameter.value)
+ saveRateEstimator(spinboxRateEstimator.value)
+ dashPlayer.reloadParameters()
+ closeOptionConnections();
+ }
+ }
+ }
+}
diff --git a/qml/Viper/Options.qml b/qml/Viper/Options.qml
new file mode 100755
index 00000000..82d3e3e7
--- /dev/null
+++ b/qml/Viper/Options.qml
@@ -0,0 +1,1710 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.5
+import QtQuick.Extras 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Controls 2.0
+import QtQuick.Layouts 1.3
+import "utils.js" as Utils
+
+Rectangle {
+ signal closeOptions
+ signal saveAdaptationLogic(string selectedAdaptationLogic, int adaptationLogicKey)
+ signal saveIcn(bool selectedIcn)
+ signal saveIcnPrefix(string selectedIcnPrefix)
+ signal saveHttpPrefix(string selectedHttpPrefix)
+ signal saveIcnSuffix(string selectedIcnSuffix)
+ signal saveHttpSuffix(string selectedHttpSuffix)
+ signal saveSegmentBufferSize(real selectedSegmentBufferSize)
+ signal saveRateAlpha(real selectedRateAlpha)
+ signal saveBufferReservoirThreshold(real selectedBufferReservoirThreshold)
+ signal saveBufferMaxThreshold(real selectedBufferMaxThreshold)
+ signal saveAdaptechFirstThreshold(real selectedAdaptechFirstThreshold)
+ signal saveAdaptechSecondThreshold(real selectedAdaptechSecondThreshold)
+ signal saveAdaptechSwitchUpMargin(real selectedAdaptechSwitchUpMargin)
+ signal saveAdaptechSlackParameter(real selectedAdaptechSlackParameter)
+ signal saveAdaptechAlpha(real selectedAdaptechAlpha)
+ signal saveBufferThreeThresholdFirst(real selectedBufferThreeThresholdFirst)
+ signal saveBufferThreeThresholdSecond(real selectedBufferThreeThresholdSecond)
+ signal saveBufferThreeThresholdThird(real selectedBufferThreeThresholdThird)
+ signal savePandaParamAlpha(real selectedPandaParamAlpha)
+ signal savePandaParamBeta(real selectedPandaParamBeta)
+ signal savePandaParamBMin(real selectedPandaParamBMin)
+ signal savePandaParamK(real selectedPandaParamK)
+ signal savePandaParamW(real selectedPandaParamW)
+ signal savePandaParamEpsilon(real selectedPandaParamEpsilon)
+ signal saveBolaBufferTarget(real selectedBolaBufferTarget)
+ signal saveBolaAlpha(real selectedBolaAlpha)
+ signal reloadRateBasedConf
+ signal reloadBufferBasedConf
+ signal reloadBufferRateBasedConf
+ signal reloadBufferThreeThresholdConf
+ signal reloadPandaConf
+ signal reloadBolaConf
+ property int heightRow: Utils.scaled(60)
+
+ function scaled(x)
+ {
+ return x*Screen.pixelDensity/Screen.logicalPixelDensity;
+ }
+
+ id: root
+ color: "#88445566"
+ property variant target
+ opacity: 0
+ radius: Utils.scaled(10)
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ enabled: false
+
+ Item {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+ id: itemAdaptationSetList
+ Label {
+ id: labelAdaptationSetList
+ color: "white"
+ anchors.top: parent.top
+ anchors.right: comboAdaptationSetList.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (comboAdaptationSetList.height - height)/2
+ text: "Video AdaptationSet"
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+
+ }
+
+ ComboBox {
+ z: parent.z + 1
+ id: comboAdaptationSetList
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ width: Utils.scaled(200)
+ enabled: true
+ textRole: "text"
+
+ model: ListModel {
+ id: adaptationLogicModel
+ ListElement { text: "Always Lowest"; }
+ ListElement { text: "Rate Based"; }
+ ListElement { text: "Buffer Based"; }
+ ListElement { text: "Buffer Rate Based"; }
+ ListElement { text: "Buffer Based Three Threshold"; }
+ ListElement { text: "Panda"; }
+ ListElement { text: "Bola"; }
+ }
+
+ onCurrentIndexChanged: {
+ switch (currentIndex) {
+ case 0:
+ case 7:
+ reloadRateBasedConf()
+ spinboxRateAlpha.value = rateAlpha*100
+ rectangleRateBasedConf.enabled = false
+ rectangleRateBasedConf.opacity = 0
+ reloadBufferBasedConf()
+ spinboxBufferReservoirThreshold.value = bufferReservoirThreshold*100
+ spinboxBufferMaxThreshold.value = bufferMaxThreshold*100
+ rectangleBufferBasedConf.enabled = false
+ rectangleBufferBasedConf.opacity = 0
+ reloadBufferRateBasedConf()
+ spinboxAdaptechFirstThreshold.value = adaptechFirstThreshold*100
+ spinboxAdaptechSecondThreshold.value = adaptechSecondThreshold*100
+ spinboxAdaptechSwitchUpMargin.value = adaptechSwitchUpMargin*100
+ spinboxAdaptechSlackParameter.value = adaptechSlackParameter*100
+ spinboxAdaptechAlpha.value = adaptechAlpha*100
+ rectangleBufferRateBasedConf.enabled = false
+ rectangleBufferRateBasedConf.opacity = 0
+ reloadBufferThreeThresholdConf()
+ spinboxBufferThreeThresoldFirst.value = bufferThreeThresholdFirst*100
+ spinboxBufferThreeThresoldSecond.value = bufferThreeThresholdSecond*100
+ spinboxBufferThreeThresoldThird.value = bufferThreeThresholdThird*100
+ rectangleBufferThreeThresholdConf.enabled = false
+ rectangleBufferThreeThresholdConf.opacity = 0
+ reloadPandaConf()
+ spinboxPandaParamAlpha.value = pandaParamAlpha*100
+ spinboxPandaParamBeta.value = pandaParamBeta*100
+ spinboxPandaParamBMin.value = pandaParamBMin*100
+ spinboxPandaParamK.value = pandaParamK*100
+ spinboxPandaParamW.value = pandaParamW
+ spinboxPandaParamEpsilon.value = pandaParamEpsilon*100
+ rectanglePandaConf.enabled = false
+ rectanglePandaConf.opacity = 0
+ reloadBolaConf()
+ spinboxBolaBufferTarget.value = bolaBufferTarget*100
+ spinboxBolaAlpha.value = bolaAlpha*100
+ rectangleBolaConf.enabled = false
+ rectangleBolaConf.opacity = 0
+ break
+ case 1:
+ rectangleRateBasedConf.enabled = true
+ rectangleRateBasedConf.opacity = 1
+ reloadBufferBasedConf()
+ spinboxBufferReservoirThreshold.value = bufferReservoirThreshold*100
+ spinboxBufferMaxThreshold.value = bufferMaxThreshold*100
+ rectangleBufferBasedConf.enabled = false
+ rectangleBufferBasedConf.opacity = 0
+ reloadBufferRateBasedConf()
+ spinboxAdaptechFirstThreshold.value = adaptechFirstThreshold*100
+ spinboxAdaptechSecondThreshold.value = adaptechSecondThreshold*100
+ spinboxAdaptechSwitchUpMargin.value = adaptechSwitchUpMargin*100
+ spinboxAdaptechSlackParameter.value = adaptechSlackParameter*100
+ spinboxAdaptechAlpha.value = adaptechAlpha*100
+ rectangleBufferRateBasedConf.enabled = false
+ rectangleBufferRateBasedConf.opacity = 0
+ reloadBufferThreeThresholdConf()
+ spinboxBufferThreeThresoldFirst.value = bufferThreeThresholdFirst*100
+ spinboxBufferThreeThresoldSecond.value = bufferThreeThresholdSecond*100
+ spinboxBufferThreeThresoldThird.value = bufferThreeThresholdThird*100
+ rectangleBufferThreeThresholdConf.enabled = false
+ rectangleBufferThreeThresholdConf.opacity = 0
+ reloadPandaConf()
+ spinboxPandaParamAlpha.value = pandaParamAlpha*100
+ spinboxPandaParamBeta.value = pandaParamBeta*100
+ spinboxPandaParamBMin.value = pandaParamBMin*100
+ spinboxPandaParamK.value = pandaParamK*100
+ spinboxPandaParamW.value = pandaParamW
+ spinboxPandaParamEpsilon.value = pandaParamEpsilon*100
+ rectanglePandaConf.enabled = false
+ rectanglePandaConf.opacity = 0
+ reloadBolaConf()
+ spinboxBolaBufferTarget.value = bolaBufferTarget*100
+ spinboxBolaAlpha.value = bolaAlpha*100
+ rectangleBolaConf.enabled = false
+ rectangleBolaConf.opacity = 0
+ break
+ case 2:
+ reloadRateBasedConf()
+ spinboxRateAlpha.value = rateAlpha*100
+ rectangleRateBasedConf.enabled = false
+ rectangleRateBasedConf.opacity = 0
+ rectangleBufferBasedConf.enabled = true
+ rectangleBufferBasedConf.opacity = 1
+ reloadBufferRateBasedConf()
+ spinboxAdaptechFirstThreshold.value = adaptechFirstThreshold*100
+ spinboxAdaptechSecondThreshold.value = adaptechSecondThreshold*100
+ spinboxAdaptechSwitchUpMargin.value = adaptechSwitchUpMargin*100
+ spinboxAdaptechSlackParameter.value = adaptechSlackParameter*100
+ spinboxAdaptechAlpha.value = adaptechAlpha*100
+ rectangleBufferRateBasedConf.enabled = false
+ rectangleBufferRateBasedConf.opacity = 0
+ reloadBufferThreeThresholdConf()
+ spinboxBufferThreeThresoldFirst.value = bufferThreeThresholdFirst*100
+ spinboxBufferThreeThresoldSecond.value = bufferThreeThresholdSecond*100
+ spinboxBufferThreeThresoldThird.value = bufferThreeThresholdThird*100
+ rectangleBufferThreeThresholdConf.enabled = false
+ rectangleBufferThreeThresholdConf.opacity = 0
+ reloadPandaConf()
+ spinboxPandaParamAlpha.value = pandaParamAlpha*100
+ spinboxPandaParamBeta.value = pandaParamBeta*100
+ spinboxPandaParamBMin.value = pandaParamBMin*100
+ spinboxPandaParamK.value = pandaParamK*100
+ spinboxPandaParamW.value = pandaParamW
+ spinboxPandaParamEpsilon.value = pandaParamEpsilon*100
+ rectanglePandaConf.enabled = false
+ rectanglePandaConf.opacity = 0
+ reloadBolaConf()
+ spinboxBolaBufferTarget.value = bolaBufferTarget*100
+ spinboxBolaAlpha.value = bolaAlpha*100
+ rectangleBolaConf.enabled = false
+ rectangleBolaConf.opacity = 0
+ break
+ case 3:
+ reloadRateBasedConf()
+ spinboxRateAlpha.value = rateAlpha*100
+ rectangleRateBasedConf.enabled = false
+ rectangleRateBasedConf.opacity = 0
+ reloadBufferBasedConf()
+ spinboxBufferReservoirThreshold.value = bufferReservoirThreshold*100
+ spinboxBufferMaxThreshold.value = bufferMaxThreshold*100
+ rectangleBufferBasedConf.enabled = false
+ rectangleBufferBasedConf.opacity = 0
+ rectangleBufferRateBasedConf.enabled = true
+ rectangleBufferRateBasedConf.opacity = 1
+ reloadBufferThreeThresholdConf()
+ spinboxBufferThreeThresoldFirst.value = bufferThreeThresholdFirst*100
+ spinboxBufferThreeThresoldSecond.value = bufferThreeThresholdSecond*100
+ spinboxBufferThreeThresoldThird.value = bufferThreeThresholdThird*100
+ rectangleBufferThreeThresholdConf.enabled = false
+ rectangleBufferThreeThresholdConf.opacity = 0
+ reloadPandaConf()
+ spinboxPandaParamAlpha.value = pandaParamAlpha*100
+ spinboxPandaParamBeta.value = pandaParamBeta*100
+ spinboxPandaParamBMin.value = pandaParamBMin*100
+ spinboxPandaParamK.value = pandaParamK*100
+ spinboxPandaParamW.value = pandaParamW
+ spinboxPandaParamEpsilon.value = pandaParamEpsilon*100
+ rectanglePandaConf.enabled = false
+ rectanglePandaConf.opacity = 0
+ reloadBolaConf()
+ spinboxBolaBufferTarget.value = bolaBufferTarget*100
+ spinboxBolaAlpha.value = bolaAlpha*100
+ rectangleBolaConf.enabled = false
+ rectangleBolaConf.opacity = 0
+ break
+ case 4:
+ reloadRateBasedConf()
+ spinboxRateAlpha.value = rateAlpha*100
+ rectangleRateBasedConf.enabled = false
+ rectangleRateBasedConf.opacity = 0
+ reloadBufferBasedConf()
+ spinboxBufferReservoirThreshold.value = bufferReservoirThreshold*100
+ spinboxBufferMaxThreshold.value = bufferMaxThreshold*100
+ rectangleBufferBasedConf.enabled = false
+ rectangleBufferBasedConf.opacity = 0
+ reloadBufferRateBasedConf()
+ spinboxAdaptechFirstThreshold.value = adaptechFirstThreshold*100
+ spinboxAdaptechSecondThreshold.value = adaptechSecondThreshold*100
+ spinboxAdaptechSwitchUpMargin.value = adaptechSwitchUpMargin*100
+ spinboxAdaptechSlackParameter.value = adaptechSlackParameter*100
+ spinboxAdaptechAlpha.value = adaptechAlpha*100
+ rectangleBufferRateBasedConf.enabled = false
+ rectangleBufferRateBasedConf.opacity = 0
+ rectangleBufferThreeThresholdConf.enabled = true
+ rectangleBufferThreeThresholdConf.opacity = 1
+ reloadPandaConf()
+ spinboxPandaParamAlpha.value = pandaParamAlpha*100
+ spinboxPandaParamBeta.value = pandaParamBeta*100
+ spinboxPandaParamBMin.value = pandaParamBMin*100
+ spinboxPandaParamK.value = pandaParamK*100
+ spinboxPandaParamW.value = pandaParamW
+ spinboxPandaParamEpsilon.value = pandaParamEpsilon*100
+ rectanglePandaConf.enabled = false
+ rectanglePandaConf.opacity = 0
+ reloadBolaConf()
+ spinboxBolaBufferTarget.value = bolaBufferTarget*100
+ spinboxBolaAlpha.value = bolaAlpha*100
+ rectangleBolaConf.enabled = false
+ rectangleBolaConf.opacity = 0
+ break
+ case 5:
+ reloadRateBasedConf()
+ spinboxRateAlpha.value = rateAlpha*100
+ rectangleRateBasedConf.enabled = false
+ rectangleRateBasedConf.opacity = 0
+ reloadBufferBasedConf()
+ spinboxBufferReservoirThreshold.value = bufferReservoirThreshold*100
+ spinboxBufferMaxThreshold.value = bufferMaxThreshold*100
+ rectangleBufferBasedConf.enabled = false
+ rectangleBufferBasedConf.opacity = 0
+ reloadBufferRateBasedConf()
+ spinboxAdaptechFirstThreshold.value = adaptechFirstThreshold*100
+ spinboxAdaptechSecondThreshold.value = adaptechSecondThreshold*100
+ spinboxAdaptechSwitchUpMargin.value = adaptechSwitchUpMargin*100
+ spinboxAdaptechSlackParameter.value = adaptechSlackParameter*100
+ spinboxAdaptechAlpha.value = adaptechAlpha*100
+ rectangleBufferRateBasedConf.enabled = false
+ rectangleBufferRateBasedConf.opacity = 0
+ reloadBufferThreeThresholdConf()
+ spinboxBufferThreeThresoldFirst.value = bufferThreeThresholdFirst*100
+ spinboxBufferThreeThresoldSecond.value = bufferThreeThresholdSecond*100
+ spinboxBufferThreeThresoldThird.value = bufferThreeThresholdThird*100
+ rectangleBufferThreeThresholdConf.enabled = false
+ rectangleBufferThreeThresholdConf.opacity = 0
+ rectanglePandaConf.enabled = true
+ rectanglePandaConf.opacity = 1
+ reloadBolaConf()
+ spinboxBolaBufferTarget.value = bolaBufferTarget*100
+ spinboxBolaAlpha.value = bolaAlpha*100
+ rectangleBolaConf.enabled = false
+ rectangleBolaConf.opacity = 0
+ break
+ case 6:
+ reloadRateBasedConf()
+ spinboxRateAlpha.value = rateAlpha*100
+ rectangleRateBasedConf.enabled = false
+ rectangleRateBasedConf.opacity = 0
+ reloadBufferBasedConf()
+ spinboxBufferReservoirThreshold.value = bufferReservoirThreshold*100
+ spinboxBufferMaxThreshold.value = bufferMaxThreshold*100
+ rectangleBufferBasedConf.enabled = false
+ rectangleBufferBasedConf.opacity = 0
+ reloadBufferRateBasedConf()
+ spinboxAdaptechFirstThreshold.value = adaptechFirstThreshold*100
+ spinboxAdaptechSecondThreshold.value = adaptechSecondThreshold*100
+ spinboxAdaptechSwitchUpMargin.value = adaptechSwitchUpMargin*100
+ spinboxAdaptechSlackParameter.value = adaptechSlackParameter*100
+ spinboxAdaptechAlpha.value = adaptechAlpha*100
+ rectangleBufferRateBasedConf.enabled = false
+ rectangleBufferRateBasedConf.opacity = 0
+ reloadBufferThreeThresholdConf()
+ spinboxBufferThreeThresoldFirst.value = bufferThreeThresholdFirst*100
+ spinboxBufferThreeThresoldSecond.value = bufferThreeThresholdSecond*100
+ spinboxBufferThreeThresoldThird.value = bufferThreeThresholdThird*100
+ rectangleBufferThreeThresholdConf.enabled = false
+ rectangleBufferThreeThresholdConf.opacity = 0
+ reloadPandaConf()
+ spinboxPandaParamAlpha.value = pandaParamAlpha*100
+ spinboxPandaParamBeta.value = pandaParamBeta*100
+ spinboxPandaParamBMin.value = pandaParamBMin*100
+ spinboxPandaParamK.value = pandaParamK*100
+ spinboxPandaParamW.value = pandaParamW
+ spinboxPandaParamEpsilon.value = pandaParamEpsilon*100
+ rectanglePandaConf.enabled = false
+ rectanglePandaConf.opacity = 0
+ rectangleBolaConf.enabled = true
+ rectangleBolaConf.opacity = 1
+ break
+ }
+ }
+ currentIndex: find(adaptationLogic)
+ }
+
+ Item {
+ id: switchRectangle
+ anchors.left: comboAdaptationSetList.right
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(12)
+
+ Label {
+ text: "TCP"
+ id: labelLegacy
+ color: "white"
+ anchors.top: parent.top
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: switchIcn.height
+ }
+
+ Switch {
+ id: switchIcn
+ height: comboAdaptationSetList.height
+ anchors.top: parent.top
+ anchors.left: labelLegacy.right
+ checked: icn
+ }
+
+ Label {
+ id: labelIcn
+ color: "white"
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.left: switchIcn.right
+ text: "ICN"
+ font.bold: true
+ font.pixelSize: switchIcn.height
+ }
+ }
+ }
+
+ Item {
+ id: itemIcnPrefix
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+
+ Label {
+ text: "ICN Prefix:"
+ id: labelIcnPrefix
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: textInputIcnPrefix.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (textInputIcnPrefix.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ TextInput {
+ width: parent.width/4*3
+ id: textInputIcnPrefix
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ font.pixelSize: Utils.scaled(20)
+ color: "white"
+ text: icnPrefix
+ }
+ }
+
+ Item {
+ id: itemIcnSuffix
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+
+ Label {
+ text: "ICN Suffix:"
+ id: labelIcnSuffix
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: textInputIcnSuffix.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (textInputIcnSuffix.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ TextInput {
+ width: parent.width/4*3
+ id: textInputIcnSuffix
+ anchors.top: parent.top
+ anchors.right: parent.right
+ font.pixelSize: Utils.scaled(20)
+ color: "white"
+ text: icnSuffix
+ }
+ }
+
+ Item {
+ id: itemHttpPrefix
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + 2*heightRow
+
+ Label {
+ text: "TCP Prefix:"
+ id: labelHttpPrefix
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: textInputHttpPrefix.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (textInputHttpPrefix.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ TextInput {
+ width: parent.width/4*3
+ id: textInputHttpPrefix
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ font.pixelSize: Utils.scaled(20)
+ color: "white"
+ text: httpPrefix
+ }
+ }
+
+ Item {
+ id: itemHttpSuffix
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + 2*heightRow
+
+ Label {
+ text: "TCP Suffix:"
+ id: labelHttpSuffix
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: textInputHttpSuffix.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (textInputHttpSuffix.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ TextInput {
+ width: parent.width/4*3
+ id: textInputHttpSuffix
+ anchors.top: parent.top
+ anchors.right: parent.right
+ font.pixelSize: Utils.scaled(20)
+ color: "white"
+ text: httpSuffix
+ }
+ }
+
+ Item {
+ id: itemSegmentBufferSize
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + 3*heightRow
+
+ Label {
+ text: "Segment Buffer Size"
+ id: labelSegmentBufferSize
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxSegmentBufferSize.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxSegmentBufferSize.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxSegmentBufferSize
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: segmentBufferSize*100
+ to: 10000
+ stepSize: 100
+ property int decimals: 0
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxSegmentBufferSize.from, spinboxSegmentBufferSize.to)
+ top: Math.max(spinboxSegmentBufferSize.from, spinboxSegmentBufferSize.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxSegmentBufferSize.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Rectangle {
+ id: rectangleRateBasedConf
+ z: parent.z + 1
+ enabled: false
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12) + 4*heightRow
+
+ Label {
+ text: "Rate Based Conf"
+ id: labelRateBasedConf
+ color: " white"
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(10)
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: Utils.scaled(20);
+ }
+
+ Item {
+ id: itemRateAlpha
+ anchors.top: labelRateBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Rate\nAlpha"
+ id: labelRateAlpha
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxRateAlpha.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxRateAlpha.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxRateAlpha
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: rateAlpha*100
+ to: 100000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxRateAlpha.from, spinboxRateAlpha.to)
+ top: Math.max(spinboxRateAlpha.from, spinboxRateAlpha.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxRateAlpha.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: rectangleBufferBasedConf
+ radius: Utils.scaled(10)
+ z: parent.z + 1
+ enabled: false
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12) + 4*heightRow
+
+ Label {
+ text: "Buffer Based Conf"
+ id: labelBufferBasedConf
+ color: " white"
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(10)
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: Utils.scaled(20);
+ }
+
+ Item {
+ id: itemBufferReservoirThreshold
+ anchors.top: labelBufferBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Buffer Reservoir\nThreshold"
+ id: labelBufferReservoirThreshold
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBufferReservoirThreshold.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBufferReservoirThreshold.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBufferReservoirThreshold
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: bufferReservoirThreshold*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBufferReservoirThreshold.from, spinboxBufferReservoirThreshold.to)
+ top: Math.max(spinboxBufferReservoirThreshold.from, spinboxBufferReservoirThreshold.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBufferReservoirThreshold.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemBufferMaxThreshold
+ anchors.top: labelBufferBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Buffer Max\nThreshold"
+ id: labelBufferMaxThreshold
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBufferMaxThreshold.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBufferMaxThreshold.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBufferMaxThreshold
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: bufferMaxThreshold*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBufferMaxThreshold.from, spinboxBufferMaxThreshold.to)
+ top: Math.max(spinboxBufferMaxThreshold.from, spinboxBufferMaxThreshold.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBufferMaxThreshold.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: rectangleBufferRateBasedConf
+ z: parent.z + 1
+ enabled: false
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12) + 4*heightRow
+
+ Label {
+ text: "Buffer Rate Based Conf"
+ id: labelBufferRateBasedConf
+ color: " white"
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(10)
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: Utils.scaled(20);
+ }
+
+ Item {
+ id: itemAdaptechFirstThreshold
+ anchors.top: labelBufferRateBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Adaptech First\nThreshold"
+ id: labelAdaptechFirstThreshold
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxAdaptechFirstThreshold.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxAdaptechFirstThreshold.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxAdaptechFirstThreshold
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: adaptechFirstThreshold*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator{
+ bottom: Math.min(spinboxAdaptechFirstThreshold.from, spinboxAdaptechFirstThreshold.to)
+ top: Math.max(spinboxAdaptechFirstThreshold.from, spinboxAdaptechFirstThreshold.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxAdaptechFirstThreshold.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemAdaptechSecondThreshold
+ anchors.top: labelBufferRateBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Adaptech\nSecond\nThreshold"
+ id: labelAdaptechSecondThreshold
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxAdaptechSecondThreshold.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxAdaptechSecondThreshold.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxAdaptechSecondThreshold
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: adaptechSecondThreshold*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxAdaptechSecondThreshold.from, spinboxAdaptechSecondThreshold.to)
+ top: Math.max(spinboxAdaptechSecondThreshold.from, spinboxAdaptechSecondThreshold.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxAdaptechSecondThreshold.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemAdaptechSwitchUpMargin
+ anchors.top: labelBufferRateBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Adaptech\nSwitchUp\nMargin"
+ id: labelAdaptechswitchUpMargin
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxAdaptechSwitchUpMargin.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxAdaptechSwitchUpMargin.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxAdaptechSwitchUpMargin
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(700)
+ from: 0
+ value: adaptechSwitchUpMargin*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxAdaptechSwitchUpMargin.from, spinboxAdaptechSwitchUpMargin.to)
+ top: Math.max(spinboxAdaptechSwitchUpMargin.from, spinboxAdaptechSwitchUpMargin.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxAdaptechSwitchUpMargin.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemAdaptechSlackParameter
+ anchors.top: labelBufferRateBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Adaptech\nSlack\nParameter"
+ id: labelAdaptechSwitchUpMargin
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxAdaptechSlackParameter.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxAdaptechSlackParameter.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxAdaptechSlackParameter
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(950)
+ from: 0
+ value: adaptechSlackParameter*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxAdaptechSlackParameter.from, spinboxAdaptechSlackParameter.to)
+ top: Math.max(spinboxAdaptechSlackParameter.from, spinboxAdaptechSlackParameter.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxAdaptechSlackParameter.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemAdaptechAlpha
+ anchors.top: labelBufferRateBasedConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+
+ Label {
+ textFormat: Text.RichText
+ text: "Adaptech\nAlpha"
+ id: labelAdaptechAlpha
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxAdaptechAlpha.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxAdaptechAlpha.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxAdaptechAlpha
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: adaptechAlpha*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxAdaptechAlpha.from, spinboxAdaptechAlpha.to)
+ top: Math.max(spinboxAdaptechAlpha.from, spinboxAdaptechAlpha.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxAdaptechAlpha.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: rectangleBufferThreeThresholdConf
+ radius: Utils.scaled(10)
+ z: parent.z + 1
+ enabled: false
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12) + 4*heightRow
+
+ Label {
+ text: "Buffer Three Conf"
+ id: labelBufferThreeThresholdConf
+ color: " white"
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(10)
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: Utils.scaled(20);
+ }
+
+ Item {
+ id: itemBufferThreeThresoldFirst
+ anchors.top: labelBufferThreeThresholdConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Buffer Three\nThreshold\nFirst"
+ id: labelBufferThreeThresoldFirst
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBufferThreeThresoldFirst.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBufferThreeThresoldFirst.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBufferThreeThresoldFirst
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: bufferThreeThresholdFirst*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBufferThreeThresoldFirst.from, spinboxBufferThreeThresoldFirst.to)
+ top: Math.max(spinboxBufferThreeThresoldFirst.from, spinboxBufferThreeThresoldFirst.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBufferThreeThresoldFirst.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemBufferThreeThresoldSecond
+ anchors.top: labelBufferThreeThresholdConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Buffer Three\nThreshold\nSecond"
+ id: labelBufferThreeThresoldSecond
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBufferThreeThresoldSecond.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBufferThreeThresoldSecond.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBufferThreeThresoldSecond
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: bufferThreeThresholdSecond*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBufferThreeThresoldSecond.from, spinboxBufferThreeThresoldSecond.to)
+ top: Math.max(spinboxBufferThreeThresoldSecond.from, spinboxBufferThreeThresoldSecond.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBufferThreeThresoldSecond.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemBufferThreeThresoldThird
+ anchors.top: labelBufferThreeThresholdConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Buffer Three\nThreshold\nThird"
+ id: labelBufferThreeThresoldThird
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBufferThreeThresoldThird.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBufferThreeThresoldThird.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBufferThreeThresoldThird
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(700)
+ from: 0
+ value: bufferThreeThresholdThird*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBufferThreeThresoldThird.from, spinboxBufferThreeThresoldThird.to)
+ top: Math.max(spinboxBufferThreeThresoldThird.from, spinboxBufferThreeThresoldThird.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBufferThreeThresoldThird.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: rectanglePandaConf
+ radius: Utils.scaled(10)
+ z: parent.z + 1
+ enabled: false
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12) + 4*heightRow
+
+ Label {
+ text: "Panda Conf"
+ id: labelPandaConf
+ color: " white"
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(10)
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: Utils.scaled(20);
+ }
+
+ Item {
+ id: itemPandaParamAlpha
+ anchors.top: labelPandaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ textFormat: Text.RichText
+ text: "Param &alpha;"
+ id: labelPandaParamAlpha
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxPandaParamAlpha.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxPandaParamAlpha.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxPandaParamAlpha
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: pandaParamAlpha*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxPandaParamAlpha.from, spinboxPandaParamAlpha.to)
+ top: Math.max(spinboxPandaParamAlpha.from, spinboxPandaParamAlpha.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxPandaParamAlpha.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+
+ Item {
+ id: itemPandaParamBeta
+ anchors.top: labelPandaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ textFormat: Text.RichText
+ text: "Param &beta;"
+ id: labelPandaParamBeta
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxPandaParamBeta.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxPandaParamBeta.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxPandaParamBeta
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: pandaParamBeta*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxPandaParamBeta.from, spinboxPandaParamBeta.to)
+ top: Math.max(spinboxPandaParamBeta.from, spinboxPandaParamBeta.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxPandaParamBeta.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemPandaParamBMin
+ anchors.top: labelPandaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ textFormat: Text.RichText
+ text: "Param B<sub>min</sub>"
+ id: labelPandaParamBMin
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxPandaParamBMin.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxPandaParamBMin.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxPandaParamBMin
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(700)
+ from: 0
+ value: pandaParamBMin*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxPandaParamBMin.from, spinboxPandaParamBMin.to)
+ top: Math.max(spinboxPandaParamBMin.from, spinboxPandaParamBMin.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxPandaParamBMin.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemPandaParamK
+ anchors.top: labelPandaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Param K"
+ id: labelPandaParamK
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxPandaParamK.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxPandaParamK.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxPandaParamK
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(950)
+ from: 0
+ value: pandaParamK*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxPandaParamK.from, spinboxPandaParamK.to)
+ top: Math.max(spinboxPandaParamK.from, spinboxPandaParamK.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxPandaParamK.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemPandaParamW
+ anchors.top: labelPandaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+
+ Label {
+ textFormat: Text.RichText
+ text: "Param &omega;"
+ id: labelPandaParamW
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxPandaParamW.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxPandaParamW.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxPandaParamW
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: pandaParamW
+ to: 1000000
+ stepSize: 1
+ }
+ }
+
+ Item {
+ id: itemPandaParamEpsilon
+ anchors.top: labelPandaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12) + heightRow
+
+ Label {
+ textFormat: Text.RichText
+ text: "Param &epsilon;"
+ id: labelPandaParamEpsilon
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxPandaParamEpsilon.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxPandaParamEpsilon.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxPandaParamEpsilon
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: pandaParamEpsilon*100
+ to: 10000
+ stepSize: 1
+ property int decimals: 2
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxPandaParamEpsilon.from, spinboxPandaParamEpsilon.to)
+ top: Math.max(spinboxPandaParamEpsilon.from, spinboxPandaParamEpsilon.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxPandaParamEpsilon.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: rectangleBolaConf
+ radius: Utils.scaled(10)
+ z: parent.z + 1
+ enabled: false
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: Utils.scaled(12) + 4*heightRow
+
+ Label {
+ text: "Bola Conf"
+ id: labelBolaConf
+ color: " white"
+ anchors.top: parent.top
+ anchors.leftMargin: Utils.scaled(10)
+ anchors.left: parent.left
+ font.bold: true
+ font.pixelSize: Utils.scaled(20);
+
+ }
+
+ Item {
+ id: itemBolaBufferTarget
+ anchors.top: labelBolaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: Utils.scaled(parent.width/2)
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Bola Buffer\nTarget"
+ id: labelBolaBufferTarget
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBolaBufferTarget.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBolaBufferTarget.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBolaBufferTarget
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(200)
+ from: 0
+ value: bolaBufferTarget*100
+ to: 100000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBolaBufferTarget.from, spinboxBolaBufferTarget.to)
+ top: Math.max(spinboxBolaBufferTarget.from, spinboxBolaBufferTarget.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBolaBufferTarget.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+
+ Item {
+ id: itemBolaAlpha
+ anchors.top: labelBolaConf.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width/2
+ anchors.topMargin: Utils.scaled(12)
+
+ Label {
+ text: "Bola\nAlpha"
+ id: labelBolaAlpha
+ color: " white"
+ anchors.top: parent.top
+ anchors.right: spinboxBolaAlpha.left
+ anchors.rightMargin: Utils.scaled(5)
+ anchors.topMargin: (spinboxBolaAlpha.height - height)/2
+ font.bold: true
+ font.pixelSize: Utils.scaled(10);
+ }
+
+ SpinBox {
+ id: spinboxBolaAlpha
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Utils.scaled(450)
+ from: 0
+ value: bolaAlpha*100
+ to: 10000
+ stepSize: 10
+ property int decimals: 1
+ property real realValue: value / 100
+
+ validator: DoubleValidator {
+ bottom: Math.min(spinboxBolaAlpha.from, spinboxBolaAlpha.to)
+ top: Math.max(spinboxBolaAlpha.from, spinboxBolaAlpha.to)
+ }
+
+ textFromValue: function(value, locale)
+ {
+ return Number(value / 100).toLocaleString(locale, 'f', spinboxBolaAlpha.decimals)
+ }
+
+ valueFromText: function(text, locale)
+ {
+ return Number.fromLocaleString(locale, text) * 100
+ }
+ }
+ }
+ }
+
+ Item {
+ id: itemButton
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: Utils.scaled(12)
+ anchors.bottomMargin: Utils.scaled(12)
+
+ Button {
+ id: cancelBtn
+ z: parent.z + 1
+ text: "Cancel"
+ anchors.right: saveBtn.left
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: Utils.scaled(5)
+
+ onClicked: {
+ closeOptions();
+ }
+ }
+
+ Button {
+ id: saveBtn
+ z: parent.z + 1
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ text: "Save"
+
+ onClicked: {
+ saveAdaptationLogic(adaptationLogicModel.get(comboAdaptationSetList.currentIndex).text, comboAdaptationSetList.currentIndex);
+ saveIcn(switchIcn.checked)
+ saveIcnPrefix(textInputIcnPrefix.text)
+ saveHttpPrefix(textInputHttpPrefix.text)
+ saveIcnSuffix(textInputIcnSuffix.text)
+ saveHttpSuffix(textInputHttpSuffix.text)
+ saveSegmentBufferSize(spinboxSegmentBufferSize.value/100)
+ saveRateAlpha(spinboxRateAlpha.value/100)
+ saveBufferReservoirThreshold(spinboxBufferReservoirThreshold.value/100)
+ saveBufferMaxThreshold(spinboxBufferMaxThreshold.value/100)
+ saveAdaptechFirstThreshold(spinboxAdaptechFirstThreshold.value/100)
+ saveAdaptechSecondThreshold(spinboxAdaptechSecondThreshold.value/100)
+ saveAdaptechSwitchUpMargin(spinboxAdaptechSwitchUpMargin.value/100)
+ saveAdaptechSlackParameter(spinboxAdaptechSlackParameter.value/100)
+ saveAdaptechAlpha(spinboxAdaptechAlpha.value/100)
+ saveBufferThreeThresholdFirst(spinboxBufferThreeThresoldFirst.value/100)
+ saveBufferThreeThresholdSecond(spinboxBufferThreeThresoldSecond.value/100)
+ saveBufferThreeThresholdThird(spinboxBufferThreeThresoldThird.value/100)
+ savePandaParamAlpha(spinboxPandaParamAlpha.value/100)
+ savePandaParamBeta(spinboxPandaParamBeta.value/100)
+ savePandaParamBMin(spinboxPandaParamBMin.value/100)
+ savePandaParamK(spinboxPandaParamK.value/100)
+ savePandaParamW(spinboxPandaParamW.value)
+ savePandaParamEpsilon(spinboxPandaParamEpsilon.value/100)
+ saveBolaBufferTarget(spinboxBolaBufferTarget.value/100)
+ saveBolaAlpha(spinboxBolaAlpha.value/100)
+ dashPlayer.reloadParameters()
+ closeOptions();
+ }
+ }
+ }
+}
diff --git a/qml/Viper/ProgressBar.qml b/qml/Viper/ProgressBar.qml
new file mode 100755
index 00000000..3d0ec228
--- /dev/null
+++ b/qml/Viper/ProgressBar.qml
@@ -0,0 +1,124 @@
+/******************************************************************************
+ Copyright (C) 2013-2016 Wang Bin <wbsecg1@gmail.com>
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+import "utils.js" as Utils
+
+Rectangle {
+ id: root
+ color: "#44eeeeee"
+ radius: Utils.scaled(5)
+ property alias value: grip.value
+ property color lineColor: "#880000ee"
+ property color gripColor: "white"
+ property real gripSize: Utils.scaled(8)
+ property real gripTolerance: Utils.scaled(3.0)
+ property real increment: 0.1
+ property bool showGrip: true
+ property bool tracking: true
+ signal valueChangedByUi
+ signal hoverAt(real value)
+ // dx, dy: only the direction. dx>0 means enter from left or leave to left
+ signal enter(point pos, point dpos)
+ signal leave(point pos, point dpos)
+
+ Rectangle {
+ anchors {
+ left: parent.left
+ verticalCenter: parent.verticalCenter
+ }
+ radius: parent.radius
+ width: grip.x + grip.radius
+ height: parent.height
+ color: displayedColor(root.lineColor)
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+
+ onClicked: {
+ if (parent.width) {
+ parent.value = mouse.x / parent.width
+ valueChangedByUi(parent.value)
+ }
+ }
+
+ onMouseXChanged: {
+ hoverAt(mouseX/parent.width)
+ }
+
+ onEntered: {
+ enter(Qt.point(mouseX, mouseY), Qt.point(0, mouseY > height/2 ? 1 : -1))
+ hoverAt(mouseX/parent.width)
+ }
+
+ onExited: {
+ leave(Qt.point(mouseX, mouseY), Qt.point(0, mouseY > height/2 ? 1 : -1))
+ }
+ }
+
+ Rectangle {
+ id: grip
+ property real value: 0
+ x: (value * parent.width - width/2)
+ anchors.verticalCenter: parent.verticalCenter
+ width: root.gripTolerance * root.gripSize
+ height: parent.height
+ radius: width/2
+ color: "transparent"
+
+ MouseArea {
+ id: mouseArea
+ enabled: root.enabled
+ anchors.fill: parent
+ drag {
+ target: grip
+ axis: Drag.XAxis
+ minimumX: -parent.width/2
+ maximumX: root.width - parent.width/2
+ }
+
+ onPositionChanged: {
+ if (drag.active)
+ updatePosition()
+ }
+
+ onReleased: {
+ updatePosition()
+ }
+
+ function updatePosition()
+ {
+ value = (grip.x + grip.width/2) / grip.parent.width
+ valueChangedByUi(value)
+ }
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: root.gripSize
+ height: parent.height
+ radius: width/2
+ color: root.showGrip ? root.gripColor : "transparent"
+ }
+ }
+
+ function displayedColor(c)
+ {
+ var tint = Qt.rgba(c.r, c.g, c.b, 0.25)
+ return enabled ? c : Qt.tint(c, tint)
+ }
+}
diff --git a/qml/Viper/Slider.qml b/qml/Viper/Slider.qml
new file mode 100755
index 00000000..058bfd8e
--- /dev/null
+++ b/qml/Viper/Slider.qml
@@ -0,0 +1,117 @@
+/******************************************************************************
+ Copyright (C) 2013-2016 Wang Bin <wbsecg1@gmail.com>
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+import "utils.js" as Utils
+
+Item {
+ id: root
+ property alias value: grip.value
+ property color fillColor: "white"
+ property color lineColor: "blue"
+ property real lineWidth: Utils.scaled(6)
+ property color gripColor: "white"
+ property real gripSize: Utils.scaled(12)
+ property real gripTolerance: Utils.scaled(3.0)
+ property int orientation: Qt.Horizontal
+ property bool hovered: false //mouseArea.containsMouse || gripMouseArea.containsMouse
+ property real max: 1
+ property real min: 0
+
+ Rectangle {
+ anchors.centerIn: parent
+ height: orientation === Qt.Horizontal ? lineWidth : parent.height
+ width: orientation === Qt.Horizontal ? parent.width : lineWidth
+ color: lineColor
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ onHoveredChanged: {
+ if (mouseX > 65535) //qt5.6 touch screen release finger becomes very large e.g. 0x7fffffff
+ return
+ hovered = mouseArea.containsMouse
+ }
+
+ onClicked: {
+ var newValue = min + (mouse.x / parent.width)*(max-min)
+ if (orientation === Qt.Horizontal) {
+ newValue = min + (mouse.x / parent.width)*(max-min)
+ } else {
+ newValue = min + (mouse.y / parent.height)*(max-min)
+ }
+ var increment = 1.0/width
+ if (Math.abs(newValue - parent.value) > parent.increment*(max-min)) {
+ if (newValue > parent.value)
+ parent.value = Math.min(max, parent.value + parent.increment*(max-min))
+ else
+ parent.value = Math.max(min, parent.value - parent.increment*(max-min))
+ }
+ }
+ }
+
+ Item {
+ id: grip
+ property real value: 0.5
+ x: orientation === Qt.Horizontal ? ((value-min)/(max-min) * parent.width - width/2) : (parent.width - width)/2
+ y: orientation === Qt.Horizontal ? (parent.height - height)/2 : ((value-min)/(max-min) * parent.height - height/2)
+ width: root.gripTolerance * root.gripSize
+ height: width
+ readonly property real radius: width/2
+
+ MouseArea {
+ id: gripMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onHoveredChanged: {
+ if (mouseX > 65535) //qt5.6 touch screen release finger becomes very large e.g. 0x7fffffff
+ return
+ hovered = gripMouseArea.containsMouse
+ }
+
+ drag {
+ target: grip
+ axis: orientation === Qt.Horizontal ? Drag.XAxis : Drag.YAxis
+ minimumX: orientation === Qt.Horizontal ? -parent.radius : 0
+ maximumX: orientation === Qt.Horizontal ? root.width - parent.radius : 0
+ minimumY: orientation === Qt.Horizontal ? 0 : -parent.radius
+ maximumY: orientation === Qt.Horizontal ? 0 : root.height - parent.radius
+ }
+
+ onPositionChanged: {
+ if (drag.active)
+ updatePosition()
+ }
+ onReleased: updatePosition()
+ function updatePosition() {
+ if (orientation === Qt.Horizontal)
+ value = min + ((grip.x + grip.radius) / grip.parent.width)*(max-min)
+ else
+ value = min + ((grip.y + grip.radius) / grip.parent.height)*(max-min)
+ }
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: root.gripSize
+ height: width
+ radius: width/2
+ color: root.gripColor
+ }
+ }
+}
diff --git a/qml/Viper/VideoCodec.qml b/qml/Viper/VideoCodec.qml
new file mode 100755
index 00000000..d07c97ec
--- /dev/null
+++ b/qml/Viper/VideoCodec.qml
@@ -0,0 +1,150 @@
+/******************************************************************************
+ QtAV: Multimedia framework based on Qt and FFmpeg
+ Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
+* This file is part of QtAV (from 2013)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+import "utils.js" as Utils
+
+Page {
+ id: root
+ title: qsTr("Video Codec")
+ height: titleHeight + detail.height + listView.height + copyMode.height + Utils.kSpacing*4
+ signal zeroCopyChanged(bool value)
+
+ QtObject {
+ id: d
+ property Item selectedItem
+ property string detail: qsTr("Takes effect on the next play")
+ }
+
+ Column {
+ anchors.fill: content
+ spacing: Utils.kSpacing
+
+ Text {
+ id: detail
+ text: d.detail
+ color: "white"
+ height: contentHeight + 1.6*Utils.kItemHeight
+ width: parent.width
+ font.pixelSize: Utils.kFontSize
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ ListView {
+ id: listView
+ contentWidth: parent.width - Utils.scaled(20)
+ height: Utils.kItemHeight
+
+ anchors {
+ //topMargin: Utils.kMargin
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ onContentWidthChanged: {
+ anchors.leftMargin = Math.max(10, (parent.width - contentWidth)/2)
+ anchors.rightMargin = anchors.leftMargin
+ width = parent.width - 2*anchors.leftMargin
+ }
+
+ orientation: ListView.Horizontal
+ spacing: Utils.scaled(6)
+ focus: true
+
+ delegate: contentDelegate
+ model: codecMode
+ }
+
+ ListModel {
+ id: codecMode
+ ListElement { name: "FFmpeg"; hardware: false; zcopy: false; description: "FFmpeg/Libav" }
+ }
+
+ Component {
+ id: contentDelegate
+ DelegateItem {
+ id: delegateItem
+ text: name
+ //width: Utils.kItemWidth
+ height: Utils.kItemHeight
+ color: "#aa000000"
+ selectedColor: "#aa0000cc"
+ border.color: "white"
+
+ onClicked: {
+ if (d.selectedItem == delegateItem)
+ return
+ if (d.selectedItem)
+ d.selectedItem.state = "baseState"
+ d.selectedItem = delegateItem
+ }
+
+ onStateChanged: {
+ if (state != "selected")
+ return
+ d.detail = description + " " + (hardware ? qsTr("hardware decoding") : qsTr("software decoding"))
+ if (name === "FFmpeg")
+ {
+ copyMode.visible = false
+ } else {
+ copyMode.visible = zcopy
+ d.detail += "\n" + qsTr("Zero Copy support") + ":" + zcopy
+ }
+ PlayerConfig.decoderPriorityNames = [ name ]
+ }
+ }
+ }
+ Button {
+ id: copyMode
+ text: qsTr("Zero copy")
+ checked: PlayerConfig.zeroCopy
+ checkable: true
+ width: parent.width
+ height: Utils.kItemHeight
+ onCheckedChanged: PlayerConfig.zeroCopy = checked
+ }
+ }
+ Component.onCompleted: {
+ if (Qt.platform.os == "windows")
+ {
+ codecMode.append({ name: "DXVA", hardware: true, zcopy: true, description: "DirectX Video Acceleration (Windows)\nUse OpenGLES(ANGLE) + D3D to support 0-copy" })
+ codecMode.append({ name: "D3D11", hardware: true, zcopy: true, description: "D3D11 Video Acceleration\n0-copy is supported under OpenGLES(ANGLE)" })
+ codecMode.append({ name: "CUDA", hardware: true, zcopy: true, description: "NVIDIA CUDA (Windows, Linux).\nH264 10bit support."})
+ } else if (Qt.platform.os == "winrt" || Qt.platform.os == "winphone") {
+ codecMode.append({ name: "D3D11", hardware: true, zcopy: true, description: "D3D11 Video Acceleration" })
+ } else if (Qt.platform.os == "osx") {
+ codecMode.append({ name: "VDA", hardware: true, zcopy: true, description: "VDA (OSX)" })
+ codecMode.append({ name: "VideoToolbox", hardware: true, zcopy: true, description: "VideoToolbox (OSX)" })
+ } else if (Qt.platform.os == "ios") {
+ codecMode.append({ name: "VideoToolbox", hardware: true, zcopy: true, description: "VideoToolbox (iOS)" })
+ } else if(Qt.platform.os == "android") {
+ codecMode.append({ name: "MediaCodec", hardware: true, zcopy: false, description: "Android 5.0 MediaCodec (H.264)" })
+ } else if (Qt.platform.os == "linux") {
+ codecMode.append({ name: "VAAPI", hardware: true, zcopy: true, description: "VA-API (Linux) " })
+ codecMode.append({ name: "CUDA", hardware: true, zcopy: true, description: "NVIDIA CUDA (Windows, Linux)"})
+ }
+ for (var i = 0; i < codecMode.count; ++i)
+ {
+ if (codecMode.get(i).name === PlayerConfig.decoderPriorityNames[0]) {
+ listView.currentIndex = i;
+ d.selectedItem = listView.currentItem
+ listView.currentItem.state = "selected"
+ break
+ }
+ }
+ }
+}
diff --git a/qml/Viper/main.qml b/qml/Viper/main.qml
new file mode 100755
index 00000000..bd90103a
--- /dev/null
+++ b/qml/Viper/main.qml
@@ -0,0 +1,945 @@
+/******************************************************************************
+ QtAV: Multimedia framework based on Qt and FFmpeg
+ Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
+* This file is part of QtAV (from 2013)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Dialogs 1.2
+import QtAV 1.7
+import QtQuick.Window 2.1
+import QtQml 2.2
+import "utils.js" as Utils
+
+Rectangle {
+ id: root
+ layer.enabled: false
+ objectName: "root"
+ width: Screen.width
+ height: Screen.height
+ color: "black"
+ signal requestFullScreen
+ signal requestNormalSize
+ property bool play: false
+ property bool pause: false
+ property bool stop: true
+ property bool buffering: false
+ property string lastPlayed: ""
+ property string adaptationLogic: ""
+ property string icnPrefix: ""
+ property string httpPrefix: ""
+ property string icnSuffix: ""
+ property string httpSuffix: ""
+ property real alpha: 0
+ property real segmentBufferSize: 0
+ property bool icn: false
+ property real rateAlpha:0
+ property real bufferReservoirThreshold: 0
+ property real bufferMaxThreshold: 0
+ property real adaptechFirstThreshold: 0
+ property real adaptechSecondThreshold: 0
+ property real adaptechSwitchUpMargin: 0
+ property real adaptechSlackParameter: 0
+ property real adaptechAlpha: 0
+ property real bufferThreeThresholdFirst: 0
+ property real bufferThreeThresholdSecond: 0
+ property real bufferThreeThresholdThird: 0
+ property real pandaParamAlpha: 0
+ property real pandaParamBeta: 0
+ property real pandaParamBMin: 0
+ property real pandaParamK: 0
+ property real pandaParamW: 0
+ property real pandaParamEpsilon: 0
+ property real bolaBufferTarget: 0
+ property real bolaAlpha: 0
+ property int screenWidth: Screen.width
+ property int screenHeight: Screen.height
+ property int windowWidth: Window.width
+ property int pixDens: Math.ceil(Screen.pixelDensity)
+ property int itemWidth: 25 * pixDens
+ property int itemHeight: 10 * pixDens
+ property int scaledMargin: 2 * pixDens
+ property int fontSize: 5 * pixDens
+ property string platformName: Qt.platform.os
+ property bool isPlaying: false
+ property string graphStatus: "stop"
+ property bool hasMpd: false
+ property bool canBuffer: false
+ property alias keyboardFocus: myKeyboard.focus
+ property bool repeat: false
+ property bool graph: false
+ property bool enabledFullScreen: false
+ property bool autotune: false
+ property int lifetime: 0
+ property int retransmissions: 0
+ property real beta: 0
+ property real drop: 0
+ property real betaWifi: 0
+ property real dropWifi: 0
+ property int delayWifi: 0
+ property real betaLte: 0
+ property real dropLte: 0
+ property int delayLte: 0
+ property int batchingParameter: 0
+ property int rateEstimator: 0
+
+ function init(argv)
+ {
+ console.log("init>>>>>screen density logical: " + Screen.logicalPixelDensity + " pixel: " + Screen.pixelDensity);
+ }
+
+ function initGraph(initGraphValue)
+ {
+ graph = initGraphValue
+ }
+
+ function initRepeat(initRepeatValue)
+ {
+ repeat = initRepeatValue
+ }
+
+ function initFullScreen(initFullScreen)
+ {
+ enabledFullScreen = initFullScreen
+ }
+
+ function setPlay()
+ {
+ play = true
+ pause = false
+ stop = false
+ buffering = false
+ }
+
+ function setLastPlayed(initLastPlayed)
+ {
+ lastPlayed = initLastPlayed
+ }
+
+ function setAdaptationLogic(initAdaptationLogic)
+ {
+ adaptationLogic = initAdaptationLogic
+ }
+
+ function setIcn(initIcn)
+ {
+ icn = initIcn
+ }
+
+ function setPause()
+ {
+ play = true
+ pause = true
+ stop = false
+ buffering = false
+ }
+
+ function startGraph()
+ {
+ graphPanel.startTimer()
+ }
+
+ function stopGraph()
+ {
+ graphPanel.stopTimer()
+ }
+
+ function pauseGraph()
+ {
+ graphPanel.pauseTimer()
+ }
+
+
+ function setStop()
+ {
+ control.setStopState()
+ }
+
+ function setBuffering()
+ {
+ canBuffer = true
+ }
+
+ function unSetBuffering()
+ {
+ canBuffer = false
+ }
+
+ VideoOutput2 {
+ id: videoOut
+ focus: false
+ opengl: true
+ fillMode: VideoOutput.PreserveAspectFit
+ anchors.fill: parent
+ source: player
+ orientation: 0
+ property real zoom: 1
+ }
+
+ AVPlayer {
+ id: player
+ objectName: "player"
+ autoPlay: true
+ videoCodecPriority: PlayerConfig.decoderPriorityNames
+ onPositionChanged: {
+ }
+
+ videoCapture {
+
+ }
+
+ onSourceChanged: {
+ videoOut.zoom = 1
+ videoOut.regionOfInterest = Qt.rect(0, 0, 0, 0)
+ }
+
+ onPlaying: {
+ control.setPlayingState()
+ }
+ onSeekFinished: {
+ }
+
+ onInternalAudioTracksChanged: {
+ }
+
+ onExternalAudioTracksChanged: {
+ }
+
+ onInternalSubtitleTracksChanged: {
+ }
+
+ onStopped: {
+ console.log("stopped ")
+ dashPlayer.onStopped(player.duration);
+ }
+
+ onPaused: {
+ console.log("else segment paused")
+ }
+
+ onError: {
+ if (error !== MediaPlayer.NoError) {
+ msg.error(errorString)
+ }
+ }
+
+ onVolumeChanged: {
+ }
+
+ onStatusChanged: {
+ }
+
+ onBufferProgressChanged: {
+ }
+ }
+
+ Subtitle {
+ id: subtitle
+ player: player
+ enabled: PlayerConfig.subtitleEnabled
+ autoLoad: PlayerConfig.subtitleAutoLoad
+ engines: PlayerConfig.subtitleEngines
+ delay: PlayerConfig.subtitleDelay
+ fontFile: PlayerConfig.assFontFile
+ fontFileForced: PlayerConfig.assFontFileForced
+ fontsDir: PlayerConfig.assFontsDir
+
+ onContentChanged: { //already enabled
+ }
+
+ onLoaded: {
+ msg.info(qsTr("Subtitle") + ": " + path.substring(path.lastIndexOf("/") + 1))
+ console.log(msg.text)
+ }
+ onSupportedSuffixesChanged: {
+
+ }
+
+ onEngineChanged: { // assume a engine canRender is only used as a renderer
+ subtitleItem.visible = canRender
+ subtitleLabel.visible = !canRender
+ }
+ onEnabledChanged: {
+ subtitleItem.visible = enabled
+ subtitleLabel.visible = enabled
+ }
+ }
+
+ Text {
+ id: msg
+ objectName: "msg"
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: Utils.scaled(20)
+ style: Text.Outline
+ styleColor: "green"
+ color: "white"
+ anchors.top: root.top
+ width: root.width
+ height: root.height / 4
+ onTextChanged: {
+ msg_timer.stop()
+ visible = true
+ msg_timer.start()
+ }
+ Timer {
+ id: msg_timer
+ interval: 2000
+ onTriggered: msg.visible = false
+ }
+ function error(txt)
+ {
+ styleColor = "red"
+ text = txt
+ }
+ function info(txt)
+ {
+ styleColor = "green"
+ text = txt
+ }
+ }
+
+ Item {
+ id: myKeyboard
+ anchors.fill: parent
+ focus: true
+ Keys.onPressed: {
+ switch (event.key) {
+ case Qt.Key_Escape:
+ break;
+ case Qt.Key_M:
+ break
+ case Qt.Key_Right:
+ break
+ case Qt.Key_Left:
+ break
+ case Qt.Key_Up:
+ break
+ case Qt.Key_Down:
+ break
+ case Qt.Key_Space:
+ break
+ case Qt.Key_Plus:
+ break;
+ case Qt.Key_Minus:
+ break;
+ case Qt.Key_F:
+ break
+ case Qt.Key_R:
+ break;
+ case Qt.Key_T:
+ break;
+ case Qt.Key_C:
+ break
+ case Qt.Key_A:
+ break
+ case Qt.Key_O:
+ break;
+ case Qt.Key_N:
+ break
+ case Qt.Key_B:
+ break;
+ case Qt.Key_G:
+ break;
+ case Qt.Key_Q:
+ if (event.modifiers & Qt.ControlModifier)
+ Qt.quit()
+ break;
+ }
+ }
+ }
+ DropArea {
+ anchors.fill: root
+ onEntered: {
+ if (!drag.hasUrls)
+ return;
+ console.log(drag.urls)
+ }
+ }
+
+ Text {
+
+ text: "Buffering..."
+ id: bufferingText
+ font.pointSize: 3*windowWidth*0.01;
+ color: "white"
+ font.family : "Helvetica"
+ opacity: canBuffer ? 1 : 0;
+ anchors.right: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ GraphPanel {
+
+ id: graphPanel
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.left: parent.right
+ opacity: {
+ if (graph)
+ opacity = 0.9
+ else
+ opacity = 0
+ }
+
+ anchors.leftMargin: parent.width/2
+ anchors.bottomMargin: control.height
+
+ }
+
+ ControlPanel {
+ id: control
+ objectName: "control"
+
+ anchors {
+ left: parent.left
+ bottom: parent.bottom
+ right: parent.right
+ leftMargin: Utils.scaled(12)
+ rightMargin: Utils.scaled(12)
+ }
+ Behavior on opacity {NumberAnimation {duration: 300} }
+
+ onStartGraph: graphPanel.startTimer()
+ onStopGraph:graphPanel.stopTimer()
+ onPauseGraph:graphPanel.pauseTimer()
+
+ onDownloadMPD: mpdList.downloadMpd()
+ onOpenMpd: {
+ lastPlayed = dashPlayer.getLastPlayed()
+ icn = dashPlayer.getIcn()
+ adaptationLogic = dashPlayer.getAdaptationLogic()
+ openMpd.enabled = true;
+ openMpd.opacity = 0.9
+ enabled = false
+ }
+
+ onOpenOptions: {
+ lastPlayed = dashPlayer.getLastPlayed()
+ icn = dashPlayer.getIcn()
+ adaptationLogic = dashPlayer.getAdaptationLogic()
+ icnPrefix = dashPlayer.getIcnPrefix()
+ httpPrefix = dashPlayer.getHttpPrefix()
+ icnSuffix = dashPlayer.getIcnSuffix()
+ httpSuffix = dashPlayer.getHttpSuffix()
+ segmentBufferSize = dashPlayer.getSegmentBufferSize()
+ rateAlpha = dashPlayer.getRateAlpha()
+ bufferReservoirThreshold = dashPlayer.getBufferReservoirThreshold()
+ bufferMaxThreshold = dashPlayer.getBufferMaxThreshold()
+ adaptechFirstThreshold = dashPlayer.getAdaptechFirstThreshold()
+ adaptechSecondThreshold = dashPlayer.getAdaptechSecondThreshold()
+ adaptechSwitchUpMargin = dashPlayer.getAdaptechSwitchUpMargin()
+ adaptechSlackParameter = dashPlayer.getAdaptechSlackParameter()
+ adaptechAlpha = dashPlayer.getAdaptechAlpha()
+ bufferThreeThresholdFirst = dashPlayer.getBufferThreeThresholdFirst()
+ bufferThreeThresholdSecond = dashPlayer.getBufferThreeThresholdSecond()
+ bufferThreeThresholdThird = dashPlayer.getBufferThreeThresholdThird()
+ pandaParamAlpha = dashPlayer.getPandaParamAlpha()
+ pandaParamBeta = dashPlayer.getPandaParamBeta()
+ pandaParamBMin = dashPlayer.getPandaParamBMin()
+ pandaParamK = dashPlayer.getPandaParamK()
+ pandaParamW = dashPlayer.getPandaParamW()
+ pandaParamEpsilon = dashPlayer.getPandaParamEpsilon()
+ bolaBufferTarget = dashPlayer.getBolaBufferTarget()
+ bolaAlpha = dashPlayer.getBolaAlpha()
+ options.enabled = true
+ options.opacity = 0.9
+ enabled = false
+ }
+
+ onOpenOptionConnections: {
+ autotune = dashPlayer.getAutotune()
+ lifetime = dashPlayer.getLifetime()
+ retransmissions = dashPlayer.getRetransmissions()
+ alpha = dashPlayer.getAlpha()
+ console.log("alpha " + alpha)
+ beta = dashPlayer.getBeta()
+ drop = dashPlayer.getDrop()
+ betaWifi = dashPlayer.getBetaWifi()
+ dropWifi = dashPlayer.getDropWifi()
+ delayWifi = dashPlayer.getDelayWifi()
+ betaLte = dashPlayer.getBetaLte()
+ dropLte = dashPlayer.getDropLte()
+ delayLte = dashPlayer.getDelayLte()
+ batchingParameter = dashPlayer.getBatchingParameter()
+ rateEstimator = dashPlayer.getRateEstimator()
+ optionConnections.enabled = true
+ optionConnections.opacity = 0.9
+ enabled = false
+ }
+
+ onOpenGraph: {
+ graph = true
+ dashPlayer.setGraph(true)
+ graphPanel.opacity = 0.9
+ }
+
+ onHideGraph: {
+ graph = false
+ dashPlayer.setGraph(false)
+ graphPanel.opacity = 0
+ }
+
+ onRepeatVideo: {
+ repeat = true
+ dashPlayer.setRepeat(true)
+ }
+
+ onDonotRepeatVideo: {
+ repeat = false
+ dashPlayer.setRepeat(false)
+ }
+
+ onResizeWindowFullScreen: {
+ var xxx = Utils.scaled(Screen.width)
+ var yyy = Utils.scaled(Screen.height)
+ root.width = Utils.scaled(Window.width)
+ root.height = Utils.scaled(Window.height)
+ }
+
+ onResizeWindow: {
+ root.width = Utils.scaled(1024)
+ root.height = Utils.scaled(768)
+ }
+
+ onSaveFullScreen: {
+ enabledFullScreen = true
+ dashPlayer.setFullScreen(true)
+ }
+
+ onSaveExitFullScreen: {
+ enabledFullScreen = false
+ dashPlayer.setFullScreen(false)
+ }
+
+ onTogglePause: {
+
+ }
+ onOpenFile: {}
+ //IF_QT53
+ onOpenUrl: {}
+ MouseArea {
+ id: ma2
+ anchors.fill: parent
+ hoverEnabled: true
+ propagateComposedEvents: true
+
+ onEntered: {
+ if(player.playbackState === MediaPlayer.PlayingState)
+ {
+ control.opacity = 1.0;
+ }
+ else
+ {
+ control.opacity = 1.0;
+ }
+ }
+
+ onExited: {
+ if(player.playbackState === MediaPlayer.PlayingState)
+ {
+ control.opacity = 0.0;
+ }
+ }
+ }
+ }
+
+ OpenMpd {
+ id: openMpd
+ enabled: false
+ objectName: "openMpd"
+
+
+ anchors.centerIn: root
+
+ onCloseOpenMpd: {
+ control.uncheckOpenBtn();
+ control.enabled = true;
+ enabled = false;
+ opacity = 0
+ }
+
+ onSaveAndPlayMpd: {
+ dashPlayer.setLastPlayed(newOpenMpd)
+ lastPlayed = newOpenMpd
+ console.log("SAVE AND PLAY THE MPD QUEEN\n")
+ console.log(adaptationLogic)
+ dashPlayer.downloadMPD(newOpenMpd, adaptationLogic, icn)
+ }
+ }
+
+ Options {
+ id: options
+ enabled: false
+ objectName: "openOption"
+
+ anchors {
+ left: parent.left
+ bottom: parent.bottom
+ right: parent.right
+ top: parent.top
+ topMargin: Utils.scaled(12)
+ bottomMargin: control.height + Utils.scaled(12)
+ leftMargin: Utils.scaled(12)
+ rightMargin: Utils.scaled(12)
+
+ }
+
+ onCloseOptions: {
+ control.uncheckOptionsBtn()
+ options.enabled = false
+ control.enabled = true
+ enabled = false;
+ opacity = 0
+ }
+
+ onSaveAdaptationLogic: {
+ dashPlayer.setAdaptationLogic(selectedAdaptationLogic)
+ adaptationLogic = selectedAdaptationLogic
+ }
+
+ onSaveIcn: {
+ dashPlayer.setIcn(selectedIcn)
+ icn = selectedIcn
+ }
+
+ onSaveIcnPrefix: {
+ dashPlayer.setIcnPrefix(selectedIcnPrefix)
+ icnPrefix = selectedIcnPrefix
+ }
+
+ onSaveHttpPrefix: {
+ dashPlayer.setHttpPrefix(selectedHttpPrefix)
+ httpPrefix = selectedHttpPrefix
+ }
+ onSaveIcnSuffix: {
+ dashPlayer.setIcnSuffix(selectedIcnSuffix)
+ icnSuffix = selectedIcnSuffix
+ }
+
+ onSaveHttpSuffix: {
+ dashPlayer.setHttpSuffix(selectedHttpSuffix)
+ httpSuffix = selectedHttpSuffix
+ }
+
+ onSaveSegmentBufferSize: {
+ dashPlayer.setSegmentBufferSize(selectedSegmentBufferSize)
+ segmentBufferSize = selectedSegmentBufferSize
+ }
+
+ onSaveRateAlpha: {
+ dashPlayer.setRateAlpha(selectedRateAlpha)
+ rateAlpha = selectedRateAlpha
+ }
+
+ onSaveBufferReservoirThreshold: {
+ dashPlayer.setBufferReservoirThreshold(selectedBufferReservoirThreshold)
+ bufferReservoirThreshold = selectedBufferReservoirThreshold
+ }
+
+ onSaveBufferMaxThreshold: {
+ dashPlayer.setBufferMaxThreshold(selectedBufferMaxThreshold)
+ bufferMaxThreshold = selectedBufferMaxThreshold
+ }
+
+ onSaveAdaptechFirstThreshold: {
+ dashPlayer.setAdaptechFirstThreshold(selectedAdaptechFirstThreshold)
+ adaptechFirstThreshold = selectedAdaptechFirstThreshold
+ }
+
+ onSaveAdaptechSecondThreshold: {
+ dashPlayer.setAdaptechSecondThreshold(selectedAdaptechSecondThreshold)
+ adaptechSecondThreshold = selectedAdaptechSecondThreshold
+ }
+
+ onSaveAdaptechSwitchUpMargin: {
+ dashPlayer.setAdaptechSwitchUpMargin(selectedAdaptechSwitchUpMargin)
+ adaptechSwitchUpMargin = selectedAdaptechSwitchUpMargin
+ }
+
+ onSaveAdaptechSlackParameter: {
+ dashPlayer.setAdaptechSlackParameter(selectedAdaptechSlackParameter)
+ adaptechSlackParameter = selectedAdaptechSlackParameter
+ }
+
+ onSaveAdaptechAlpha: {
+ dashPlayer.setAdaptechAlpha(selectedAdaptechAlpha)
+ adaptechAlpha = selectedAdaptechAlpha
+ }
+
+ onSaveBufferThreeThresholdFirst: {
+ dashPlayer.setBufferThreeThresholdFirst(selectedBufferThreeThresholdFirst)
+ bufferThreeThresholdFirst = selectedBufferThreeThresholdFirst
+ }
+
+ onSaveBufferThreeThresholdSecond: {
+ dashPlayer.setBufferThreeThresholdSecond(selectedBufferThreeThresholdSecond)
+ bufferThreeThresholdSecond = selectedBufferThreeThresholdSecond
+ }
+
+ onSaveBufferThreeThresholdThird: {
+ dashPlayer.setBufferThreeThresholdThird(selectedBufferThreeThresholdThird)
+ bufferThreeThresholdThird = selectedBufferThreeThresholdThird
+ }
+
+ onSavePandaParamAlpha: {
+ dashPlayer.setPandaParamAlpha(selectedPandaParamAlpha)
+ pandaParamAlpha = selectedPandaParamAlpha
+ }
+
+ onSavePandaParamBeta: {
+ dashPlayer.setPandaParamBeta(selectedPandaParamBeta)
+ pandaParamBeta = selectedPandaParamBeta
+ }
+
+ onSavePandaParamBMin: {
+ dashPlayer.setPandaParamBMin(selectedPandaParamBMin)
+ pandaParamBMin = selectedPandaParamBMin
+ }
+
+ onSavePandaParamK: {
+ dashPlayer.setPandaParamK(selectedPandaParamK)
+ pandaParamK = selectedPandaParamK
+ }
+
+ onSavePandaParamW: {
+ dashPlayer.setPandaParamW(selectedPandaParamW)
+ pandaParamW = selectedPandaParamW
+ }
+
+ onSavePandaParamEpsilon: {
+ dashPlayer.setPandaParamEpsilon(selectedPandaParamEpsilon)
+ pandaParamEpsilon = selectedPandaParamEpsilon
+ }
+
+ onSaveBolaBufferTarget: {
+ dashPlayer.setBolaBufferTarget(selectedBolaBufferTarget)
+ bolaBufferTarget = selectedBolaBufferTarget
+ }
+
+ onSaveBolaAlpha: {
+ dashPlayer.setBolaAlpha(selectedBolaAlpha)
+ bolaAlpha = selectedBolaAlpha
+ }
+
+ onReloadBufferBasedConf: {
+ bufferReservoirThreshold = dashPlayer.getBufferReservoirThreshold()
+ bufferMaxThreshold = dashPlayer.getBufferMaxThreshold()
+ }
+
+ onReloadBufferRateBasedConf:{
+ adaptechFirstThreshold = dashPlayer.getAdaptechFirstThreshold()
+ adaptechSecondThreshold = dashPlayer.getAdaptechSecondThreshold()
+ adaptechSwitchUpMargin = dashPlayer.getAdaptechSwitchUpMargin()
+ adaptechSlackParameter = dashPlayer.getAdaptechSlackParameter()
+ adaptechAlpha = dashPlayer.getAdaptechAlpha()
+ }
+
+ onReloadBufferThreeThresholdConf: {
+ bufferThreeThresholdFirst = dashPlayer.getBufferThreeThresholdFirst()
+ bufferThreeThresholdSecond = dashPlayer.getBufferThreeThresholdSecond()
+ bufferThreeThresholdThird = dashPlayer.getBufferThreeThresholdThird()
+ }
+
+ onReloadPandaConf: {
+ pandaParamAlpha = dashPlayer.getPandaParamAlpha()
+ pandaParamBeta = dashPlayer.getPandaParamBeta()
+ pandaParamBMin = dashPlayer.getPandaParamBMin()
+ pandaParamK = dashPlayer.getPandaParamK()
+ pandaParamW = dashPlayer.getPandaParamW()
+ pandaParamEpsilon = dashPlayer.getPandaParamEpsilon()
+
+ }
+
+ onReloadBolaConf: {
+ bolaBufferTarget = dashPlayer.getBolaBufferTarget()
+
+ }
+ }
+
+ OptionConnections {
+ id: optionConnections
+ enabled: false
+ objectName: "openOption"
+
+ anchors {
+ left: parent.left
+ bottom: parent.bottom
+ right: parent.right
+ top: parent.top
+ topMargin: Utils.scaled(12)
+ bottomMargin: control.height + Utils.scaled(12)
+ leftMargin: Utils.scaled(12)
+ rightMargin: Utils.scaled(12)
+ }
+
+ onCloseOptionConnections: {
+ control.uncheckOptionConnectionsBtn()
+ optionConnections.enabled = false
+ control.enabled = true
+ enabled = false;
+ opacity = 0
+ }
+
+ onSaveAutotune: {
+ dashPlayer.setAutotune(selectedAutotune)
+ autotune = selectedAutotune
+ }
+
+ onSaveLifetime: {
+ dashPlayer.setLifetime(selectedLifetime)
+ lifetime = selectedLifetime
+ }
+
+ onSaveRetransmissions: {
+ dashPlayer.setRetransmissions(selectedRetransmissions)
+ retransmissions = selectedRetransmissions
+ }
+
+ onSaveAlpha: {
+ dashPlayer.setAlpha(selectedAlpha)
+ alpha = selectedAlpha
+ }
+
+ onSaveBeta: {
+ dashPlayer.setBeta(selectedBeta)
+ beta = selectedBeta
+ }
+
+ onSaveDrop: {
+ dashPlayer.setDrop(selectedDrop)
+ drop = selectedDrop
+ }
+
+ onSaveBetaWifi: {
+ dashPlayer.setBetaWifi(selectedBetaWifi)
+ betaWifi = selectedBetaWifi
+ }
+
+ onSaveDropWifi: {
+ dashPlayer.setDropWifi(selectedDropWifi)
+ dropWifi = selectedDropWifi
+ }
+
+ onSaveDelayWifi: {
+ dashPlayer.setDelayWifi(selectedDelayWifi)
+ delayWifi = selectedDelayWifi
+ }
+
+ onSaveBetaLte: {
+ dashPlayer.setBetaLte(selectedBetaLte)
+ betaLte = selectedBetaLte
+ }
+
+ onSaveDropLte: {
+ dashPlayer.setDropLte(selectedDropLte)
+ dropLte = selectedDropLte
+ }
+
+ onSaveDelayLte: {
+ dashPlayer.setDelayLte(selectedDelayLte)
+ delayLte = selectedDelayLte
+ }
+
+ onSaveBatchingParameter: {
+ dashPlayer.setBatchingParameter(selectedBatchingParameter)
+ batchingParameter = selectedBatchingParameter
+ }
+
+ onSaveRateEstimator: {
+ dashPlayer.setRateEstimator(selectedRateEstimator)
+ rateAlpha = selectedRateEstimator
+ }
+ }
+
+ //IF_QT53
+ Dialog {
+ id: urlDialog
+ standardButtons: StandardButton.Open | StandardButton.Cancel
+ title: qsTr("Open a URL")
+ Rectangle {
+ color: "black"
+ anchors.top: parent.top
+ height: Utils.kItemHeight
+ width: parent.width
+ TextInput {
+ id: urlEdit
+ color: "orange"
+ font.pixelSize: Utils.kFontSize
+ anchors.fill: parent
+ }
+ }
+ onAccepted: player.source = urlEdit.displayText
+ }
+
+ //ENDIF_QT53
+ FileDialog {
+ id: fileDialog
+ title: "Please choose a media file"
+ selectMultiple: true
+ folder: PlayerConfig.lastFile
+ onAccepted: {
+ var sub, av
+ for (var i = 0; i < fileUrls.length; ++i)
+ {
+ var s = fileUrls[i].toString()
+ if (s.endsWith(".srt")
+ || s.endsWith(".ass")
+ || s.endsWith(".ssa")
+ || s.endsWith(".sub")
+ || s.endsWith(".idx") //vob
+ || s.endsWith(".mpl2")
+ || s.endsWith(".smi")
+ || s.endsWith(".sami")
+ || s.endsWith(".sup")
+ || s.endsWith(".txt"))
+ sub = fileUrls[i]
+ else
+ av = fileUrls[i]
+ }
+ if (sub)
+ {
+ subtitle.autoLoad = false
+ subtitle.file = sub
+ } else
+ {
+ subtitle.autoLoad = PlayerConfig.subtitleAutoLoad
+ subtitle.file = ""
+ }
+ if (av)
+ {
+ player.source = av
+ PlayerConfig.lastFile = av
+ }
+ }
+ }
+ Connections {
+ target: Qt.application
+ onStateChanged: { //since 5.1
+ if (Qt.platform.os === "winrt" || Qt.platform.os === "winphone") //paused by system
+ return
+ // winrt is handled by system
+ switch (Qt.application.state) {
+ case Qt.ApplicationSuspended:
+ case Qt.ApplicationHidden:
+ player.pause()
+ break
+ default:
+ break
+ }
+ }
+ }
+
+
+}
diff --git a/qml/Viper/utils.js b/qml/Viper/utils.js
new file mode 100755
index 00000000..ad00957c
--- /dev/null
+++ b/qml/Viper/utils.js
@@ -0,0 +1,100 @@
+/******************************************************************************
+ QtAV: Multimedia framework based on Qt and FFmpeg
+ Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
+* This file is part of QtAV (from 2013)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+******************************************************************************/
+
+var kItemWidth = scaled(60)
+var kItemHeight = scaled(30)
+var kMargin = scaled(8)
+var kFontSize = scaled(16)
+var kSpacing = scaled(4)
+
+// "/xxx" will be resolved as qrc:///xxx. while "xxx" is "qrc:///QMLDIR/xxx
+var resprefix = Qt.resolvedUrl(" ").substring(0, 4) == "qrc:" ? "/" : ""
+
+function resurl(s) { //why called twice if in qrc?
+ return resprefix + s
+}
+
+String.prototype.startsWith = function(s) {
+ return this.indexOf(s) === 0;
+};
+
+String.prototype.endsWith = function(suffix) {
+ return this.indexOf(suffix, this.length - suffix.length) !== -1;
+};
+
+function fileName(path) {
+ return path.substring(path.lastIndexOf("/") + 1)
+}
+
+function msec2string(t) {
+ t = Math.floor(t/1000)
+ var ss = t%60
+ t = (t-ss)/60
+ var mm = t%60
+ var hh = (t-mm)/60
+ if (ss < 10)
+ ss = "0" + ss
+ if (mm < 10)
+ mm = "0" + mm
+ if (hh < 10)
+ hh = "0" + hh
+ return hh + ":" + mm +":" + ss
+}
+
+function scaled(x) {
+ //console.log("scaleRatio: " + scaleRatio + "; " + x + ">>>" + x*scaleRatio);
+ return x * scaleRatio;
+}
+
+
+function htmlEscaped(s) {
+ if (!s) {
+ return '';
+ }
+ var escaped = '';
+ var namedHtml = {
+ '38': '&amp;',
+ '60': '&lt;',
+ '62': '&gt;',
+ '34': '&quot;',
+ '160': '&nbsp;',
+ '162': '&cent;',
+ '163': '&pound;',
+ '164': '&curren;',
+ '169': '&copy;',
+ '174': '&reg;',
+ };
+ var wasNewLine = 0;
+ for (var i = 0, il = s.length; i < il; ++i) {
+ var c = s.charCodeAt(i);
+ var es = namedHtml[c];
+ if (typeof es !== 'undefined') {
+ wasNewLine = 0;
+ escaped += es;
+ } else {
+ if (c === 13 || c === 10) {
+ if (wasNewLine == 0)
+ escaped += '<br>';
+ wasNewLine++;
+ } else {
+ wasNewLine = 0;
+ escaped += String.fromCharCode(c);
+ }
+ }
+ }
+ return escaped;
+}