diff options
author | Alex Merry <alex.merry@cs.ox.ac.uk> | 2011-11-01 19:43:04 +0000 |
---|---|---|
committer | Alex Merry <alex.merry@cs.ox.ac.uk> | 2011-11-01 19:43:04 +0000 |
commit | be5b3bf09f01b488bbc0429a7cbd8e7980a9bb7e (patch) | |
tree | bd0e7eba3638dfa27c88775a09d6f111960e2f2e | |
parent | a3031aea445a095c14c772e383e088b35c2be707 (diff) |
More work on the player interface test
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpris2/interfacetest.cpp | 9 | ||||
-rw-r--r-- | mpris2/interfacetest.h | 3 | ||||
-rw-r--r-- | mpris2/playerinterfacetest.cpp | 349 | ||||
-rw-r--r-- | mpris2/playerinterfacetest.h | 12 | ||||
-rw-r--r-- | mpris2/rootinterfacetest.cpp | 4 | ||||
-rw-r--r-- | mpris2/rootinterfacetest.h | 1 | ||||
-rw-r--r-- | ui/playertest.ui | 448 |
8 files changed, 818 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bbdd637..559ead2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ qt4_wrap_cpp (mpristester_SRCS ) qt4_wrap_ui (mpristester_SRCS ui/roottest.ui + ui/playertest.ui ui/window.ui ) add_executable (mpristester ${mpristester_SRCS}) diff --git a/mpris2/interfacetest.cpp b/mpris2/interfacetest.cpp index 12dfca9..50638dd 100644 --- a/mpris2/interfacetest.cpp +++ b/mpris2/interfacetest.cpp @@ -122,18 +122,20 @@ bool InterfaceTest::checkPropValid(const QString& propName, QVariant::Type expTy return false; } else if (props[propName].type() != expType) { // FIXME: generate D-Bus type description - const char * gotTypeCh = props[propName].typeName(); + const char * gotTypeCh = QDBusMetaType::typeToSignature(props[propName].userType()); QString gotType = gotTypeCh ? QString::fromAscii(gotTypeCh) : "<unknown>"; - const char * expTypeCh = QVariant::typeToName(expType); + const char * expTypeCh = QDBusMetaType::typeToSignature(expType); QString expType = expTypeCh ? QString::fromAscii(expTypeCh) : "<unknown>"; - emit interfaceError(Property, propName, "Property " + propName + " has type " + gotType + ", but should be type " + expType); + emit interfaceError(Property, propName, "Property " + propName + " has type '" + gotType + "', but should be type '" + expType + "'"); return false; } else if (oldProps.contains(propName)) { // FIXME: QVariant equality only works for builtin types if (props[propName] != oldProps[propName]) { outOfDateProperties.insert(propName, props[propName]); props[propName] = oldProps[propName]; + // don't check right now + return false; } } return true; @@ -201,6 +203,7 @@ void InterfaceTest::_m_propertiesChanged(const QString& interface, outOfDateProperties.remove(*j); ++j; } + checkConsistency(); emit propertiesChanged(changedPropsList); } diff --git a/mpris2/interfacetest.h b/mpris2/interfacetest.h index c400fec..2de85e3 100644 --- a/mpris2/interfacetest.h +++ b/mpris2/interfacetest.h @@ -124,13 +124,14 @@ namespace Mpris2 virtual void checkProps(const QVariantMap& oldProps = QVariantMap()) = 0; virtual void checkUpdatedProperty(const QString& propName) = 0; + virtual void checkConsistency(const QVariantMap& oldProps = QVariantMap()) = 0; QDBusInterface* iface; QVariantMap props; + QVariantMap outOfDateProperties; // prop name -> new value private: QDBusInterface* propsIface; - QVariantMap outOfDateProperties; // prop name -> new value QTimer* delayedCheckTimer; QMap<QString,uint> propertyUpdateWarningCount; }; diff --git a/mpris2/playerinterfacetest.cpp b/mpris2/playerinterfacetest.cpp index 8d9949d..0731eac 100644 --- a/mpris2/playerinterfacetest.cpp +++ b/mpris2/playerinterfacetest.cpp @@ -18,9 +18,7 @@ #include "playerinterfacetest.h" -#include <QDBusInterface> -#include <QDBusMessage> -#include <QDBusReply> +#include <QtDBus> #define MPRIS2_PLAYER_IFACE "org.mpris.MediaPlayer2.Player" @@ -37,7 +35,35 @@ PlayerInterfaceTest::~PlayerInterfaceTest() void PlayerInterfaceTest::checkUpdatedProperty(const QString& propName) { - + if (propName == "CanControl") { + checkPropValid("CanControl", QVariant::Bool); + } else if (propName == "CanGoNext") { + checkControlProp("CanGoNext"); + } else if (propName == "CanGoPrevious") { + checkControlProp("CanGoPrevious"); + } else if (propName == "CanPlay") { + checkControlProp("CanPlay"); + } else if (propName == "CanPause") { + checkControlProp("CanPause"); + } else if (propName == "CanSeek") { + checkControlProp("CanSeek"); + } else if (propName == "Shuffle") { + checkPropValid("Shuffle", QVariant::Bool); + } else if (propName == "Volume") { + checkVolume(); + } else if (propName == "PlaybackStatus") { + checkPlaybackStatus(); + } else if (propName == "LoopStatus") { + checkLoopStatus(); + } else if (propName == "MinimumRate") { + checkMinimumRate(); + } else if (propName == "MaximumRate") { + checkMaximumRate(); + } else if (propName == "Rate") { + checkPropValid("Rate", QVariant::Double); + } else if (propName == "Metadata") { + checkMetadata(); + } } void PlayerInterfaceTest::checkProps(const QVariantMap& oldProps) @@ -62,6 +88,13 @@ void PlayerInterfaceTest::checkProps(const QVariantMap& oldProps) emit interfaceInfo(Property, "LoopStatus", "Optional property not implemented"); } + checkMinimumRate(oldProps); + checkMaximumRate(oldProps); + checkPropValid("Rate", QVariant::Double, oldProps); + checkMetadata(oldProps); + checkPosition(oldProps); + + checkConsistency(); } void PlayerInterfaceTest::checkControlProp(const QString& propName, const QVariantMap& oldProps) @@ -118,3 +151,311 @@ void PlayerInterfaceTest::checkPlaybackStatus(const QVariantMap& oldProps) "Invalid value: '" + playbackStatus + "'"); } } + +void PlayerInterfaceTest::checkMaximumRate(const QVariantMap& oldProps) +{ + if (!checkPropValid("MaximumRate", QVariant::Double, oldProps)) + return; + double maxRate = properties().value("MaximumRate").toDouble(); + if (maxRate < 1.0) { + emit interfaceWarning(Property, "MaximumRate", + "Maximum rate should not be less than 1.0"); + } +} + +void PlayerInterfaceTest::checkMinimumRate(const QVariantMap& oldProps) +{ + if (!checkPropValid("MinimumRate", QVariant::Double, oldProps)) + return; + double minRate = properties().value("MinimumRate").toDouble(); + if (minRate > 1.0) { + emit interfaceWarning(Property, "MinimumRate", + "Minimum rate should not be greater than 1.0"); + } + if (minRate < 0.0) { + emit interfaceInfo(Property, "MinimumRate", + "Minimum rate is negative"); + } +} + +void PlayerInterfaceTest::checkRate(const QVariantMap& oldProps) +{ + if (!checkPropValid("Rate", QVariant::Double, oldProps)) + return; + double rate = properties().value("Rate").toDouble(); + if (qFuzzyCompare(rate, 0.0)) { + emit interfaceError(Property, "Rate", + "Rate must not be 0.0"); + } +} + +void PlayerInterfaceTest::checkMetadata(const QVariantMap& oldProps) +{ + if (!properties().contains("Metadata")) { + emit interfaceError(Property, "Metadata", "Property Metadata is missing"); + return; + } + if (!properties().value("Metadata").canConvert<QDBusArgument>()) { + const char * gotTypeCh = QDBusMetaType::typeToSignature(props["Metadata"].userType()); + QString gotType = gotTypeCh ? QString::fromAscii(gotTypeCh) : "<unknown>"; + emit interfaceError(Property, "Metadata", "Property Metadata has type " + gotType + ", but should be type a{sv}"); + return; + } + QVariantMap metadata; + QDBusArgument arg = properties().value("Metadata").value<QDBusArgument>(); + arg >> metadata; + + if (oldProps.contains("Metadata") && + oldProps.value("Metadata").canConvert<QDBusArgument>()) + { + QVariantMap oldMetadata; + oldProps.value("Metadata").value<QDBusArgument>() >> oldMetadata; + if (metadata != oldMetadata) { + outOfDateProperties.insert("Metadata", props["Metadata"]); + props["Metadata"] = oldProps["Metadata"]; + return; + } + } + if (metadata.isEmpty()) { + emit interfaceInfo(Property, "Metadata", + "No metadata provided"); + return; + } + + if (!metadata.contains("mpris:trackid")) { + emit interfaceError(Property, "Metadata", + "No mpris:trackid entry for the current track"); + } else if (metadata.value("mpris:trackid").type() != QVariant::String) { + emit interfaceError(Property, "Metadata", + "mpris:trackid entry is not a string"); + } else if (metadata.value("mpris:trackid").toString().isEmpty()) { + emit interfaceError(Property, "Metadata", + "mpris:trackid entry is an empty string"); + } + + checkMetadataEntry(metadata, "mpris:length", QVariant::LongLong); + + if (checkMetadataEntry(metadata, "mpris:artUrl", QVariant::Url)) { + QString artUrl = metadata.value("mpris:artUrl").toString(); + QUrl asUrl(artUrl, QUrl::StrictMode); + if (asUrl.scheme() != "file" && asUrl.scheme() != "http" && asUrl.scheme() != "https") { + emit interfaceInfo(Property, "Metadata", + "mpris:artUrl has a scheme (" + asUrl.scheme() + ") which not all clients may recognise"); + } else { + if (asUrl.scheme() == "file") { + if (!QFile::exists(asUrl.toLocalFile())) { + emit interfaceInfo(Property, "Metadata", + "mpris:artUrl references a file that does not exist"); + } + } + // FIXME: check network files + } + } + + Q_FOREACH( QString key, metadata.keys() ) { + if (!key.startsWith("xesam:")) { + if (key != "mpris:trackid" && + key != "mpris:length" && + key != "mpris:artUrl") + { + emit interfaceWarning(Property, "Metadata", + "Unrecognised entry " + key); + } + } + } + + checkMetadataEntry(metadata, "xesam:album", QVariant::String); + checkMetadataEntry(metadata, "xesam:albumArtist", QVariant::StringList); + checkMetadataEntry(metadata, "xesam:artist", QVariant::StringList); + checkMetadataEntry(metadata, "xesam:asText", QVariant::String); + checkMetadataEntry(metadata, "xesam:audioBpm", QVariant::Int); + checkMetadataEntry(metadata, "xesam:autoRating", QVariant::Double); + checkMetadataEntry(metadata, "xesam:comment", QVariant::StringList); + checkMetadataEntry(metadata, "xesam:composer", QVariant::StringList); + checkMetadataEntry(metadata, "xesam:contentCreator", QVariant::DateTime); + checkMetadataEntry(metadata, "xesam:discNumber", QVariant::Int); + checkMetadataEntry(metadata, "xesam:firstUsed", QVariant::DateTime); + checkMetadataEntry(metadata, "xesam:genre", QVariant::StringList); + checkMetadataEntry(metadata, "xesam:lastUsed", QVariant::DateTime); + checkMetadataEntry(metadata, "xesam:lyricist", QVariant::StringList); + checkMetadataEntry(metadata, "xesam:title", QVariant::String); + checkMetadataEntry(metadata, "xesam:trackNumber", QVariant::Int); + checkMetadataEntry(metadata, "xesam:url", QVariant::Url); + checkMetadataEntry(metadata, "xesam:useCount", QVariant::Int); + checkMetadataEntry(metadata, "xesam:userRating", QVariant::Double); +} + +bool PlayerInterfaceTest::checkMetadataEntry(const QVariantMap& metadata, const QString& entry, QVariant::Type expType) +{ + if (metadata.contains(entry)) { + QVariant value = metadata.value(entry); + + bool propertyTypeError = false; + bool propertyTypeWarning = false; + QVariant::Type realExpectedType = expType; + if (expType == QVariant::DateTime || expType == QVariant::Url) { + realExpectedType = QVariant::String; + } + + // be lax about integers + if (realExpectedType == QVariant::Int) { + if (value.type() == QVariant::UInt || + value.type() == QVariant::LongLong || + value.type() == QVariant::ULongLong) + { + propertyTypeWarning = true; + } else if (value.type() != QVariant::Int) { + propertyTypeError = true; + } + } else if (realExpectedType == QVariant::UInt || realExpectedType == QVariant::LongLong) { + if (value.type() == QVariant::ULongLong) { + propertyTypeWarning = true; + } else if (value.type() != realExpectedType) { + propertyTypeError = true; + } + } else if (value.type() != realExpectedType) { + propertyTypeError = true; + } + + if (propertyTypeError || propertyTypeWarning) { + const char * gotTypeCh = QDBusMetaType::typeToSignature(value.userType()); + QString gotType = gotTypeCh ? QString::fromAscii(gotTypeCh) : "<unknown>"; + const char * expTypeCh = QDBusMetaType::typeToSignature(realExpectedType); + QString expType = expTypeCh ? QString::fromAscii(expTypeCh) : "<unknown>"; + if (propertyTypeError) { + emit interfaceError(Property, "Metadata", + entry + " entry is of type '" + gotType + "' but should have been of type '" + expType + "'"); + return false; + } else { + emit interfaceWarning(Property, "Metadata", + entry + " entry is of type '" + gotType + "' but should have been of type '" + expType + "'"); + return true; + } + } + + // extra checks for special types + if (expType == QVariant::DateTime) { + QDateTime dtValue = QDateTime::fromString(value.toString(), Qt::ISODate); + if (!dtValue.isValid()) { + emit interfaceError(Property, "Metadata", + entry + " entry does not contain a valid date/time string (value was " + value.toString() + ")"); + return false; + } + } else if (expType == QVariant::Url) { + if (value.toString().isEmpty()) { + return false; + } else { + QUrl asUrl(value.toString(), QUrl::StrictMode); + if (!asUrl.isValid()) { + emit interfaceError(Property, "Metadata", + entry + " entry is not a valid URL"); + return false; + } + } + } + return true; + } + return false; +} + +void PlayerInterfaceTest::checkPosition(const QVariantMap& oldProps) +{ + if (!checkPropValid("Position", QVariant::LongLong, oldProps)) + return; + + qint64 position = properties().value("Position").toLongLong(); + if (position < 0) { + emit interfaceError(Property, "Position", + "Negative position value"); + } +} + +void PlayerInterfaceTest::checkConsistency(const QVariantMap& oldProps) +{ + checkRateConsistency(); + checkPositionConsistency(); + checkPredictedPosition(); +} + +void PlayerInterfaceTest::checkPositionConsistency(const QVariantMap& oldProps) +{ + if (!properties().contains("Position") || + !properties().contains("Metadata") || + !properties().value("Metadata").canConvert<QDBusArgument>() + ) { + return; + } + + qint64 position = properties().value("Position").toLongLong(); + + QVariantMap metadata; + properties().value("Metadata").value<QDBusArgument>() >> metadata; + if (!metadata.contains("mpris:length")) { + return; + } + qint64 length = metadata.value("mpris:length").toLongLong(); + + // drop out if the length and position have not changed + if (oldProps.contains("Position") && + oldProps.value("Position") == position && + oldProps.contains("Metadata") && + oldProps.value("Metadata").canConvert<QDBusArgument>()) + { + QVariantMap oldMetadata; + oldProps.value("Metadata").value<QDBusArgument>() >> oldMetadata; + if (oldMetadata.contains("mpris:length")) { + if (length == oldMetadata.value("mpris:length").toLongLong()) { + return; + } + } + } + + if (position > length) { + emit interfaceError(Property, "Position", + "Position is greater than the track length"); + } +} + +void PlayerInterfaceTest::checkRateConsistency(const QVariantMap& oldProps) +{ + if (properties().value("MaximumRate") != oldProps.value("MaximumRate") || + properties().value("MinimumRate") != oldProps.value("MinimumRate")) + { + if (properties().contains("MaximumRate") && properties().contains("MinimumRate")) { + double minRate = properties().value("MinimumRate").toDouble(); + double maxRate = properties().value("MaximumRate").toDouble(); + if (minRate > maxRate) { + emit interfaceError(Property, "MinimumRate", + "Minimum rate must not be greater than maximum rate"); + } + } + } + if (properties().value("Rate") != oldProps.value("Rate") || + properties().value("MaximumRate") != oldProps.value("MaximumRate") || + properties().value("MinimumRate") != oldProps.value("MinimumRate")) + { + if (properties().contains("Rate")) { + double rate = properties().value("Rate").toDouble(); + if (properties().contains("MaximumRate")) { + double maxRate = properties().value("MaximumRate").toDouble(); + if (rate > maxRate) { + emit interfaceError(Property, "Rate", + "Rate must not be greater than maximum rate"); + } + } + if (properties().contains("MinimumRate")) { + double minRate = properties().value("MinimumRate").toDouble(); + if (minRate > rate) { + emit interfaceError(Property, "Rate", + "Rate must not be less than minimum rate"); + } + } + } + } +} + +void PlayerInterfaceTest::checkPredictedPosition() +{ + // FIXME: check predicted position +} + diff --git a/mpris2/playerinterfacetest.h b/mpris2/playerinterfacetest.h index 900e72d..33e682d 100644 --- a/mpris2/playerinterfacetest.h +++ b/mpris2/playerinterfacetest.h @@ -19,7 +19,7 @@ #ifndef MPRIS2_PLAYERINTERFACETEST_H #define MPRIS2_PLAYERINTERFACETEST_H -#include <../../home/alex/src/mpristester/mpris2/interfacetest.h> +#include "interfacetest.h" namespace Mpris2 { @@ -34,12 +34,22 @@ namespace Mpris2 { protected: virtual void checkUpdatedProperty(const QString& propName); virtual void checkProps(const QVariantMap& oldProps = QVariantMap()); + virtual void checkConsistency(const QVariantMap& oldProps = QVariantMap()); private: void checkControlProp(const QString& propName, const QVariantMap& oldProps = QVariantMap()); void checkVolume(const QVariantMap& oldProps = QVariantMap()); void checkLoopStatus(const QVariantMap& oldProps = QVariantMap()); void checkPlaybackStatus(const QVariantMap& oldProps = QVariantMap()); + void checkMinimumRate(const QVariantMap& oldProps = QVariantMap()); + void checkMaximumRate(const QVariantMap& oldProps = QVariantMap()); + void checkRate(const QVariantMap& oldProps = QVariantMap()); + void checkPosition(const QVariantMap& oldProps = QVariantMap()); + void checkMetadata(const QVariantMap& oldProps = QVariantMap()); + void checkRateConsistency(const QVariantMap& oldProps = QVariantMap()); + void checkPositionConsistency(const QVariantMap& oldProps = QVariantMap()); + void checkPredictedPosition(); + bool checkMetadataEntry(const QVariantMap& metadata, const QString& entry, QVariant::Type type); }; } diff --git a/mpris2/rootinterfacetest.cpp b/mpris2/rootinterfacetest.cpp index 7359fa0..f7e8475 100644 --- a/mpris2/rootinterfacetest.cpp +++ b/mpris2/rootinterfacetest.cpp @@ -132,4 +132,8 @@ void RootInterfaceTest::testRaise() } } +void RootInterfaceTest::checkConsistency(const QVariantMap& oldProps) +{ +} + // vim:et:sw=4:sts=4 diff --git a/mpris2/rootinterfacetest.h b/mpris2/rootinterfacetest.h index 5e4481a..b29db35 100644 --- a/mpris2/rootinterfacetest.h +++ b/mpris2/rootinterfacetest.h @@ -57,6 +57,7 @@ namespace Mpris2 protected: virtual void checkProps(const QVariantMap& oldProps = QVariantMap()); virtual void checkUpdatedProperty(const QString& propName); + virtual void checkConsistency(const QVariantMap& oldProps = QVariantMap()); private: void checkPropertyIdentity(const QVariantMap& oldProps = QVariantMap()); diff --git a/ui/playertest.ui b/ui/playertest.ui new file mode 100644 index 0000000..f9bbd7f --- /dev/null +++ b/ui/playertest.ui @@ -0,0 +1,448 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PlayerTestForm</class> + <widget class="QWidget" name="PlayerTestForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>667</width> + <height>675</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Playback status:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="playbackStatusLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Loop status:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="loopStatusLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Shuffle:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="shuffleLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Volume:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="volumeLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Maximum rate:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="maxRateLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Minimum rate:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="minRateLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Rate:</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLabel" name="rateLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Last received position:</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLabel" name="lastKnownPosLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Predicted position:</string> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QLabel" name="estPosLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="9" column="0"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Can control:</string> + </property> + </widget> + </item> + <item row="9" column="1"> + <widget class="QLabel" name="canControlLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="10" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Can play:</string> + </property> + </widget> + </item> + <item row="11" column="0"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>Can pause:</string> + </property> + </widget> + </item> + <item row="12" column="0"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>Can go previous:</string> + </property> + </widget> + </item> + <item row="13" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Can go next:</string> + </property> + </widget> + </item> + <item row="13" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="canGoNextLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="nextBtn"> + <property name="text"> + <string>Next</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="14" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Can seek:</string> + </property> + </widget> + </item> + <item row="14" column="1"> + <widget class="QLabel" name="canSeekLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item row="12" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="canGoPrevLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="prevBtn"> + <property name="text"> + <string>Previous</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="10" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLabel" name="canPlayLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="playBtn"> + <property name="text"> + <string>Play</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="stopBtn"> + <property name="text"> + <string>Stop</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="11" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLabel" name="canPauseLbl"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string><unknown></string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pauseBtn"> + <property name="text"> + <string>Pause</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="playPauseBtn"> + <property name="text"> + <string>Play/Pause</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Metadata</string> + </property> + </widget> + </item> + <item> + <widget class="QTableView" name="metadataTableView"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLineEdit" name="openUriEdit"/> + </item> + <item> + <widget class="QPushButton" name="openUriBtn"> + <property name="text"> + <string>Open URI</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QSpinBox" name="seekSpinBox"> + <property name="suffix"> + <string>µs</string> + </property> + <property name="minimum"> + <number>-999999999</number> + </property> + <property name="maximum"> + <number>999999999</number> + </property> + <property name="singleStep"> + <number>1000000</number> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="seekBtn"> + <property name="text"> + <string>Seek by</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QLabel" name="label_32"> + <property name="text"> + <string>Track id:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="setPosTrackIdEdit"/> + </item> + <item> + <widget class="QLabel" name="label_33"> + <property name="text"> + <string>Position:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="setPosSpinBox"> + <property name="suffix"> + <string>µs</string> + </property> + <property name="minimum"> + <number>-999999999</number> + </property> + <property name="maximum"> + <number>999999999</number> + </property> + <property name="singleStep"> + <number>1000000</number> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="setPosBtn"> + <property name="text"> + <string>Set position</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> |