H264 downloadable codec - code adjustments + fix advanced settings
This commit is contained in:
parent
425751413d
commit
d11b3bce3d
13 changed files with 81 additions and 111 deletions
|
|
@ -81,6 +81,7 @@
|
||||||
#include "core/variant/VariantList.hpp"
|
#include "core/variant/VariantList.hpp"
|
||||||
#include "core/videoSource/VideoSourceDescriptorGui.hpp"
|
#include "core/videoSource/VideoSourceDescriptorGui.hpp"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/Constants.hpp"
|
#include "tool/Constants.hpp"
|
||||||
#include "tool/EnumsToString.hpp"
|
#include "tool/EnumsToString.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
|
|
@ -434,10 +435,10 @@ void App::initCore() {
|
||||||
mLinphoneThread->getThreadId(),
|
mLinphoneThread->getThreadId(),
|
||||||
[this]() mutable {
|
[this]() mutable {
|
||||||
lInfo() << log().arg("Updating downloaded codec files");
|
lInfo() << log().arg("Updating downloaded codec files");
|
||||||
Utils::updateCodecs(); // removing codec updates suffic (.in) before the core is created.
|
ToolModel::updateCodecs(); // removing codec updates suffic (.in) before the core is created.
|
||||||
lInfo() << log().arg("Starting Core");
|
lInfo() << log().arg("Starting Core");
|
||||||
CoreModel::getInstance()->start();
|
CoreModel::getInstance()->start();
|
||||||
Utils::loadDownloadedCodecs();
|
ToolModel::loadDownloadedCodecs();
|
||||||
auto coreStarted = CoreModel::getInstance()->getCore()->getGlobalState() == linphone::GlobalState::On;
|
auto coreStarted = CoreModel::getInstance()->getCore()->getGlobalState() == linphone::GlobalState::On;
|
||||||
lDebug() << log().arg("Creating SettingsModel");
|
lDebug() << log().arg("Creating SettingsModel");
|
||||||
SettingsModel::create();
|
SettingsModel::create();
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ private:
|
||||||
QString mDownloadUrl;
|
QString mDownloadUrl;
|
||||||
QString mInstallName;
|
QString mInstallName;
|
||||||
QString mCheckSum;
|
QString mCheckSum;
|
||||||
bool mInstalled;
|
|
||||||
QString mVersion;
|
QString mVersion;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,6 @@ QString PayloadTypeCore::getMimeType() {
|
||||||
return mMimeType;
|
return mMimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PayloadTypeCore::getDownloadable() {
|
bool PayloadTypeCore::isDownloadable() {
|
||||||
return mDownloadable;
|
return mDownloadable;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class PayloadTypeCore : public QObject, public AbstractObject {
|
||||||
DECLARE_CORE_MEMBER(QString, recvFmtp, RecvFmtp)
|
DECLARE_CORE_MEMBER(QString, recvFmtp, RecvFmtp)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Family { None, Audio, Video, Text };
|
enum Family { Audio, Video, Text };
|
||||||
|
|
||||||
static QSharedPointer<PayloadTypeCore> create(Family family,
|
static QSharedPointer<PayloadTypeCore> create(Family family,
|
||||||
const std::shared_ptr<linphone::PayloadType> &payloadType);
|
const std::shared_ptr<linphone::PayloadType> &payloadType);
|
||||||
|
|
@ -48,7 +48,7 @@ public:
|
||||||
|
|
||||||
void setSelf(QSharedPointer<PayloadTypeCore> me);
|
void setSelf(QSharedPointer<PayloadTypeCore> me);
|
||||||
Family getFamily();
|
Family getFamily();
|
||||||
bool getDownloadable();
|
bool isDownloadable();
|
||||||
QString getMimeType();
|
QString getMimeType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
#include "core/path/Paths.hpp"
|
#include "core/path/Paths.hpp"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <linphone++/linphone.hh>
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
|
@ -56,7 +57,7 @@ void PayloadTypeList::setSelf(QSharedPointer<PayloadTypeList> me) {
|
||||||
QList<QSharedPointer<PayloadTypeCore>> *payloadTypes = new QList<QSharedPointer<PayloadTypeCore>>();
|
QList<QSharedPointer<PayloadTypeCore>> *payloadTypes = new QList<QSharedPointer<PayloadTypeCore>>();
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
|
||||||
Utils::loadDownloadedCodecs();
|
ToolModel::loadDownloadedCodecs();
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
for (auto payloadType : CoreModel::getInstance()->getCore()->getAudioPayloadTypes()) {
|
for (auto payloadType : CoreModel::getInstance()->getCore()->getAudioPayloadTypes()) {
|
||||||
|
|
|
||||||
|
|
@ -32,33 +32,16 @@ PayloadTypeProxy::PayloadTypeProxy(QObject *parent) : LimitProxy(parent) {
|
||||||
PayloadTypeProxy::~PayloadTypeProxy() {
|
PayloadTypeProxy::~PayloadTypeProxy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
PayloadTypeCore::Family PayloadTypeProxy::getFamily() const {
|
|
||||||
return dynamic_cast<SortFilterList *>(sourceModel())->mFamily;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PayloadTypeProxy::setFamily(PayloadTypeCore::Family data) {
|
|
||||||
auto list = dynamic_cast<SortFilterList *>(sourceModel());
|
|
||||||
if (list->mFamily != data) {
|
|
||||||
list->mFamily = data;
|
|
||||||
familyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PayloadTypeProxy::isDownloadable() const {
|
|
||||||
return dynamic_cast<SortFilterList *>(sourceModel())->mDownloadable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PayloadTypeProxy::setDownloadable(bool data) {
|
|
||||||
auto list = dynamic_cast<SortFilterList *>(sourceModel());
|
|
||||||
if (list->mDownloadable != data) {
|
|
||||||
list->mDownloadable = data;
|
|
||||||
downloadableChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PayloadTypeProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
bool PayloadTypeProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||||
auto payload = qobject_cast<PayloadTypeList *>(sourceModel())->getAt<PayloadTypeCore>(sourceRow);
|
auto payload = qobject_cast<PayloadTypeList *>(sourceModel())->getAt<PayloadTypeCore>(sourceRow);
|
||||||
return payload->getFamily() == mFamily && payload->getDownloadable() == mDownloadable;
|
int payloadFlag = PayloadTypeProxyFiltering::All;
|
||||||
|
payloadFlag += payload->isDownloadable() ? PayloadTypeProxyFiltering::Downloadable
|
||||||
|
: PayloadTypeProxyFiltering::NotDownloadable;
|
||||||
|
auto family = payload->getFamily();
|
||||||
|
payloadFlag += family == PayloadTypeCore::Family::Audio ? PayloadTypeProxyFiltering::Audio : 0;
|
||||||
|
payloadFlag += family == PayloadTypeCore::Family::Video ? PayloadTypeProxyFiltering::Video : 0;
|
||||||
|
payloadFlag += family == PayloadTypeCore::Family::Text ? PayloadTypeProxyFiltering::Text : 0;
|
||||||
|
return mFilterType == payloadFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PayloadTypeProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
bool PayloadTypeProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const {
|
||||||
|
|
|
||||||
|
|
@ -30,26 +30,24 @@
|
||||||
class PayloadTypeProxy : public LimitProxy, public AbstractObject {
|
class PayloadTypeProxy : public LimitProxy, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(PayloadTypeCore::Family family READ getFamily WRITE setFamily NOTIFY familyChanged)
|
|
||||||
Q_PROPERTY(bool downloadable READ isDownloadable WRITE setDownloadable NOTIFY downloadableChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DECLARE_SORTFILTER_CLASS(PayloadTypeCore::Family mFamily; bool mDownloadable;)
|
enum PayloadTypeProxyFiltering {
|
||||||
|
All = 0,
|
||||||
|
Audio = 2,
|
||||||
|
Video = 4,
|
||||||
|
Text = 8,
|
||||||
|
Downloadable = 16,
|
||||||
|
NotDownloadable = 32
|
||||||
|
};
|
||||||
|
Q_ENUMS(PayloadTypeProxyFiltering)
|
||||||
|
|
||||||
|
DECLARE_SORTFILTER_CLASS()
|
||||||
|
|
||||||
Q_INVOKABLE void reload();
|
Q_INVOKABLE void reload();
|
||||||
|
|
||||||
PayloadTypeProxy(QObject *parent = Q_NULLPTR);
|
PayloadTypeProxy(QObject *parent = Q_NULLPTR);
|
||||||
~PayloadTypeProxy();
|
~PayloadTypeProxy();
|
||||||
|
|
||||||
PayloadTypeCore::Family getFamily() const;
|
|
||||||
void setFamily(PayloadTypeCore::Family data);
|
|
||||||
bool isDownloadable() const;
|
|
||||||
void setDownloadable(bool data);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void familyChanged();
|
|
||||||
void downloadableChanged();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSharedPointer<PayloadTypeList> mPayloadTypeList;
|
QSharedPointer<PayloadTypeList> mPayloadTypeList;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QLibrary>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(ToolModel)
|
DEFINE_ABSTRACT_OBJECT(ToolModel)
|
||||||
|
|
@ -304,3 +306,47 @@ bool ToolModel::friendIsInFriendList(const std::shared_ptr<linphone::FriendList>
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load downloaded codecs like OpenH264 (needs to be after core is created and has loaded its plugins, as
|
||||||
|
// reloadMsPlugins modifies plugin path for the factory)
|
||||||
|
void ToolModel::loadDownloadedCodecs() {
|
||||||
|
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
||||||
|
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
||||||
|
QDirIterator it(Paths::getCodecsDirPath());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QFileInfo info(it.next());
|
||||||
|
const QString filename(info.fileName());
|
||||||
|
if (QLibrary::isLibrary(filename)) {
|
||||||
|
qInfo() << QStringLiteral("Loading `%1` symbols...").arg(filename);
|
||||||
|
if (!QLibrary(info.filePath()).load()) // lib.load())
|
||||||
|
qWarning() << QStringLiteral("Failed to load `%1` symbols.").arg(filename);
|
||||||
|
else qInfo() << QStringLiteral("Loaded `%1` symbols...").arg(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoreModel::getInstance()->getCore()->reloadMsPlugins("");
|
||||||
|
#endif // if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes .in suffix from downloaded updates.
|
||||||
|
// Updates are downloaded with .in suffix as they can't overwrite already loaded plugin
|
||||||
|
// they are loaded at next app startup.
|
||||||
|
|
||||||
|
void ToolModel::updateCodecs() {
|
||||||
|
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
||||||
|
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
||||||
|
static const QString codecSuffix = QStringLiteral(".%1").arg(Constants::LibraryExtension);
|
||||||
|
|
||||||
|
QDirIterator it(Paths::getCodecsDirPath());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QFileInfo info(it.next());
|
||||||
|
if (info.suffix() == QLatin1String("in")) {
|
||||||
|
QString codecName = info.completeBaseName();
|
||||||
|
if (codecName.endsWith(codecSuffix)) {
|
||||||
|
QString codecPath = info.dir().path() + QDir::separator() + codecName;
|
||||||
|
QFile::remove(codecPath);
|
||||||
|
QFile::rename(info.filePath(), codecPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ public:
|
||||||
|
|
||||||
static bool friendIsInFriendList(const std::shared_ptr<linphone::FriendList> &friendList,
|
static bool friendIsInFriendList(const std::shared_ptr<linphone::FriendList> &friendList,
|
||||||
const std::shared_ptr<linphone::Friend> &f);
|
const std::shared_ptr<linphone::Friend> &f);
|
||||||
|
static void loadDownloadedCodecs();
|
||||||
|
static void updateCodecs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,8 @@
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDirIterator>
|
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QLibrary>
|
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
@ -1439,47 +1437,3 @@ void Utils::checkDownloadedCodecsUpdates() {
|
||||||
if (codec->shouldDownloadUpdate()) codec->downloadAndExtract(true);
|
if (codec->shouldDownloadUpdate()) codec->downloadAndExtract(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load downloaded codecs like OpenH264 (needs to be after core is created and has loaded its plugins, as
|
|
||||||
// reloadMsPlugins modifies plugin path for the factory)
|
|
||||||
void Utils::loadDownloadedCodecs() {
|
|
||||||
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
|
||||||
QDirIterator it(Paths::getCodecsDirPath());
|
|
||||||
while (it.hasNext()) {
|
|
||||||
QFileInfo info(it.next());
|
|
||||||
const QString filename(info.fileName());
|
|
||||||
if (QLibrary::isLibrary(filename)) {
|
|
||||||
qInfo() << QStringLiteral("Loading `%1` symbols...").arg(filename);
|
|
||||||
if (!QLibrary(info.filePath()).load()) // lib.load())
|
|
||||||
qWarning() << QStringLiteral("Failed to load `%1` symbols.").arg(filename);
|
|
||||||
else qInfo() << QStringLiteral("Loaded `%1` symbols...").arg(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CoreModel::getInstance()->getCore()->reloadMsPlugins("");
|
|
||||||
#endif // if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes .in suffix from downloaded updates.
|
|
||||||
// Updates are downloaded with .in suffix as they can't overwrite already loaded plugin
|
|
||||||
// they are loaded at next app startup.
|
|
||||||
|
|
||||||
void Utils::updateCodecs() {
|
|
||||||
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
|
||||||
static const QString codecSuffix = QStringLiteral(".%1").arg(Constants::LibraryExtension);
|
|
||||||
|
|
||||||
QDirIterator it(Paths::getCodecsDirPath());
|
|
||||||
while (it.hasNext()) {
|
|
||||||
QFileInfo info(it.next());
|
|
||||||
if (info.suffix() == QLatin1String("in")) {
|
|
||||||
QString codecName = info.completeBaseName();
|
|
||||||
if (codecName.endsWith(codecSuffix)) {
|
|
||||||
QString codecPath = info.dir().path() + QDir::separator() + codecName;
|
|
||||||
QFile::remove(codecPath);
|
|
||||||
QFile::rename(info.filePath(), codecPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,6 @@ public:
|
||||||
static QString computeUserAgent();
|
static QString computeUserAgent();
|
||||||
static QList<QSharedPointer<DownloadablePayloadTypeCore>> getDownloadableVideoPayloadTypes();
|
static QList<QSharedPointer<DownloadablePayloadTypeCore>> getDownloadableVideoPayloadTypes();
|
||||||
static void checkDownloadedCodecsUpdates();
|
static void checkDownloadedCodecsUpdates();
|
||||||
static void loadDownloadedCodecs();
|
|
||||||
static void updateCodecs();
|
|
||||||
|
|
||||||
static inline QString coreStringToAppString(const std::string &str) {
|
static inline QString coreStringToAppString(const std::string &str) {
|
||||||
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ AbstractSettingsLayout {
|
||||||
Layout.leftMargin: 64 * DefaultStyle.dp
|
Layout.leftMargin: 64 * DefaultStyle.dp
|
||||||
Repeater {
|
Repeater {
|
||||||
model: PayloadTypeProxy {
|
model: PayloadTypeProxy {
|
||||||
family: PayloadTypeCore.Audio
|
filterType: PayloadTypeProxy.Audio | PayloadTypeProxy.NotDownloadable
|
||||||
}
|
}
|
||||||
SwitchSetting {
|
SwitchSetting {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -151,7 +151,7 @@ AbstractSettingsLayout {
|
||||||
Repeater {
|
Repeater {
|
||||||
model: PayloadTypeProxy {
|
model: PayloadTypeProxy {
|
||||||
id: videoPayloadTypeProxy
|
id: videoPayloadTypeProxy
|
||||||
family: PayloadTypeCore.Video
|
filterType: PayloadTypeProxy.Video | PayloadTypeProxy.NotDownloadable
|
||||||
}
|
}
|
||||||
SwitchSetting {
|
SwitchSetting {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -164,26 +164,15 @@ AbstractSettingsLayout {
|
||||||
Repeater {
|
Repeater {
|
||||||
model: PayloadTypeProxy {
|
model: PayloadTypeProxy {
|
||||||
id: downloadableVideoPayloadTypeProxy
|
id: downloadableVideoPayloadTypeProxy
|
||||||
family: PayloadTypeCore.Video
|
filterType: PayloadTypeProxy.Video | PayloadTypeProxy.Downloadable
|
||||||
downloadable: true
|
|
||||||
}
|
}
|
||||||
SwitchSetting {
|
SwitchSetting {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
titleText: Utils.capitalizeFirstLetter(modelData.core.mimeType)
|
titleText: Utils.capitalizeFirstLetter(modelData.core.mimeType)
|
||||||
subTitleText: modelData.core.encoderDescription
|
subTitleText: modelData.core.encoderDescription
|
||||||
onCheckChanged: function(checked) {
|
onCheckedChanged: function(checked) {
|
||||||
if (checked)
|
if (checked)
|
||||||
UtilsCpp.getMainWindow().showConfirmationLambdaPopup("",
|
Utils.openCodecOnlineInstallerDialog(mainWindow, modelData.core)
|
||||||
qsTr("Installation"),
|
|
||||||
qsTr("Télécharger le codec ") + Utils.capitalizeFirstLetter(modelData.core.mimeType) + " ("+modelData.core.encoderDescription+")"+" ?",
|
|
||||||
function (confirmed) {
|
|
||||||
if (confirmed) {
|
|
||||||
UtilsCpp.getMainWindow().showLoadingPopup(qsTr("Téléchargement en cours ..."))
|
|
||||||
modelData.core.downloadAndExtract()
|
|
||||||
} else
|
|
||||||
setChecked(false)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -232,8 +232,7 @@ AbstractWindow {
|
||||||
// H264 Cisco codec download
|
// H264 Cisco codec download
|
||||||
PayloadTypeProxy {
|
PayloadTypeProxy {
|
||||||
id: downloadableVideoPayloadTypeProxy
|
id: downloadableVideoPayloadTypeProxy
|
||||||
family: PayloadTypeCore.Video
|
filterType: PayloadTypeProxy.Video | PayloadTypeProxy.Downloadable
|
||||||
downloadable: true
|
|
||||||
}
|
}
|
||||||
Repeater {
|
Repeater {
|
||||||
id: codecDownloader
|
id: codecDownloader
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue