1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qmediapluginloader_p.h"
41#include <QtCore/qcoreapplication.h>
42#include <QtCore/qdebug.h>
43#include <QtCore/qjsonarray.h>
44#include <private/qfactoryloader_p.h>
45
46#include "qmediaserviceproviderplugin.h"
47
48QT_BEGIN_NAMESPACE
49
50QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity caseSensitivity):
51 m_iid(iid)
52{
53#if defined(Q_OS_ANDROID)
54 m_location = QString(location).replace(QLatin1Char('/'), QLatin1Char('_'));
55#else
56 m_location = QString::fromLatin1(str: "/%1").arg(a: location);
57#endif
58 m_factoryLoader = new QFactoryLoader(m_iid, m_location, caseSensitivity);
59 loadMetadata();
60}
61
62QMediaPluginLoader::~QMediaPluginLoader()
63{
64 delete m_factoryLoader;
65}
66
67QStringList QMediaPluginLoader::keys() const
68{
69 return m_metadata.keys();
70}
71
72QObject* QMediaPluginLoader::instance(QString const &key)
73{
74 if (!m_metadata.contains(akey: key))
75 return nullptr;
76
77 int idx = m_metadata.value(akey: key).first().value(QStringLiteral("index")).toDouble();
78 if (idx < 0)
79 return nullptr;
80
81 return m_factoryLoader->instance(index: idx);
82}
83
84QList<QObject*> QMediaPluginLoader::instances(QString const &key)
85{
86 if (!m_metadata.contains(akey: key))
87 return QList<QObject*>();
88
89 QList<QString> keys;
90 QList<QObject *> objects;
91 const auto list = m_metadata.value(akey: key);
92 for (const QJsonObject &jsonobj : list) {
93 int idx = jsonobj.value(QStringLiteral("index")).toDouble();
94 if (idx < 0)
95 continue;
96
97 QObject *object = m_factoryLoader->instance(index: idx);
98 if (!objects.contains(t: object)) {
99 QJsonArray arr = jsonobj.value(QStringLiteral("Keys")).toArray();
100 keys.append(t: !arr.isEmpty() ? arr.at(i: 0).toString() : QStringLiteral(""));
101 objects.append(t: object);
102 }
103 }
104
105 static const bool showDebug = qEnvironmentVariableIntValue(varName: "QT_DEBUG_PLUGINS");
106 static const QStringList preferredPlugins =
107 qEnvironmentVariable(varName: "QT_MULTIMEDIA_PREFERRED_PLUGINS").split(sep: QLatin1Char(','), behavior: Qt::SkipEmptyParts);
108 for (int i = preferredPlugins.size() - 1; i >= 0; --i) {
109 auto name = preferredPlugins[i];
110 bool found = false;
111 for (int j = 0; j < keys.size(); ++j) {
112 if (!keys[j].startsWith(s: name))
113 continue;
114
115 auto obj = objects[j];
116 objects.removeAt(i: j);
117 objects.prepend(t: obj);
118 auto k = keys[j];
119 keys.removeAt(i: j);
120 keys.prepend(t: k);
121 found = true;
122 break;
123 }
124
125 if (showDebug && !found)
126 qWarning() << "QMediaPluginLoader: pattern" << name << "did not match any loaded plugin";
127 }
128
129 if (showDebug)
130 qDebug() << "QMediaPluginLoader: loaded plugins for key" << key << ":" << keys;
131
132 return objects;
133}
134
135void QMediaPluginLoader::loadMetadata()
136{
137#if !defined QT_NO_DEBUG
138 const bool showDebug = qgetenv(varName: "QT_DEBUG_PLUGINS").toInt() > 0;
139#endif
140
141#if !defined QT_NO_DEBUG
142 if (showDebug)
143 qDebug() << "QMediaPluginLoader: loading metadata for iid " << m_iid << " at location " << m_location;
144#endif
145
146 if (!m_metadata.isEmpty()) {
147#if !defined QT_NO_DEBUG
148 if (showDebug)
149 qDebug() << "QMediaPluginLoader: already loaded metadata, returning";
150#endif
151 return;
152 }
153
154 QList<QJsonObject> meta = m_factoryLoader->metaData();
155 for (int i = 0; i < meta.size(); i++) {
156 QJsonObject jsonobj = meta.at(i).value(QStringLiteral("MetaData")).toObject();
157 jsonobj.insert(QStringLiteral("index"), value: i);
158#if !defined QT_NO_DEBUG
159 if (showDebug)
160 qDebug() << "QMediaPluginLoader: Inserted index " << i << " into metadata: " << jsonobj;
161#endif
162
163 QJsonArray arr = jsonobj.value(QStringLiteral("Services")).toArray();
164 // Preserve compatibility with older plugins (made before 5.1) in which
165 // services were declared in the 'Keys' property
166 if (arr.isEmpty())
167 arr = jsonobj.value(QStringLiteral("Keys")).toArray();
168
169 for (const QJsonValue &value : qAsConst(t&: arr)) {
170 QString key = value.toString();
171
172 if (!m_metadata.contains(akey: key)) {
173#if !defined QT_NO_DEBUG
174 if (showDebug)
175 qDebug() << "QMediaPluginLoader: Inserting new list for key: " << key;
176#endif
177 m_metadata.insert(akey: key, avalue: QList<QJsonObject>());
178 }
179
180 m_metadata[key].append(t: jsonobj);
181 }
182 }
183}
184
185QT_END_NAMESPACE
186
187

source code of qtmultimedia/src/multimedia/qmediapluginloader.cpp