25#include "backendinterface.h"
26#include "medianode_p.h"
27#include "mediaobject.h"
28#include "audiooutput.h"
29#include "globalstatic_p.h"
30#include "objectdescription.h"
31#include "platformplugin.h"
32#include "phononconfig_p.h"
33#include "phononnamespace_p.h"
35#include <QCoreApplication>
38#include <QPluginLoader>
41#include <QApplication>
49class FactoryPrivate :
public Phonon::Factory::Sender
51 friend QObject *Factory::backend(
bool);
55 ~FactoryPrivate()
override;
56 bool tryCreateBackend(
const QString &path);
58#ifndef QT_NO_PHONON_PLATFORMPLUGIN
59 PlatformPlugin *platformPlugin();
61 PlatformPlugin *m_platformPlugin;
62 bool m_noPlatformPlugin;
73 void objectDestroyed(
QObject *);
75 void objectDescriptionChanged(ObjectDescriptionType);
78PHONON_GLOBAL_STATIC(Phonon::FactoryPrivate, globalFactory)
80static inline void ensureLibraryPathSet()
82#ifdef PHONON_PLUGIN_PATH
83 static bool done =
false;
91void Factory::setBackend(
QObject *b)
93 Q_ASSERT(globalFactory->m_backendObject ==
nullptr);
94 globalFactory->m_backendObject = b;
97bool FactoryPrivate::tryCreateBackend(
const QString &path)
101 pDebug() <<
"attempting to load" <<
path;
102 if (!pluginLoader.load()) {
103 pDebug() << Q_FUNC_INFO <<
" load failed:" << pluginLoader.errorString();
106 pDebug() << pluginLoader.instance();
107 m_backendObject = pluginLoader.instance();
108 if (m_backendObject) {
113 pluginLoader.unload();
118bool FactoryPrivate::createBackend()
120 pDebug() << Q_FUNC_INFO <<
"Phonon" << PHONON_VERSION_STR <<
"trying to create backend...";
122 Q_ASSERT(m_backendObject ==
nullptr);
127 const QByteArray backendEnv = qgetenv(
"PHONON_BACKEND");
129#ifndef QT_NO_PHONON_PLATFORMPLUGIN
130 PlatformPlugin *f = globalFactory->platformPlugin();
131 if (f && backendEnv.
isEmpty()) {
134 m_backendObject = f->createBackend();
138 if (!m_backendObject) {
139 const auto backends = Factory::findBackends();
141 for (
const auto &backend : backends) {
142 if (tryCreateBackend(backend.pluginPath)) {
147 if (!m_backendObject) {
148 pWarning() << Q_FUNC_INFO <<
"phonon backend plugin could not be loaded";
153 pDebug() << Q_FUNC_INFO
155 << m_backendObject->property(
"backendName").toString()
157 << m_backendObject->property(
"backendVersion").toString()
160 connect(m_backendObject, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
161 SLOT(objectDescriptionChanged(ObjectDescriptionType)));
165 pWarning() << Q_FUNC_INFO <<
"Trying to use Phonon with QT_NO_LIBRARY defined. "
166 "That is currently not supported";
171FactoryPrivate::FactoryPrivate()
173#ifndef QT_NO_PHONON_PLATFORMPLUGIN
174 m_platformPlugin(nullptr),
175 m_noPlatformPlugin(false),
177 m_backendObject(nullptr)
182 qAddPostRoutine(globalFactory.destroy);
185FactoryPrivate::~FactoryPrivate()
187 for (
int i = 0; i < mediaNodePrivateList.count(); ++i) {
188 mediaNodePrivateList.at(i)->deleteBackendObject();
190 if (objects.size() > 0) {
191 pError() <<
"The backend objects are not deleted as was requested.";
194 delete m_backendObject;
195#ifndef QT_NO_PHONON_PLATFORMPLUGIN
196 delete m_platformPlugin;
200void FactoryPrivate::objectDescriptionChanged(ObjectDescriptionType type)
202#ifdef PHONON_METHODTEST
205 pDebug() << Q_FUNC_INFO <<
type;
207 case AudioOutputDeviceType:
208 emit availableAudioOutputDevicesChanged();
210 case AudioCaptureDeviceType:
211 emit availableAudioCaptureDevicesChanged();
213 case VideoCaptureDeviceType:
214 emit availableVideoCaptureDevicesChanged();
223Factory::Sender *Factory::sender()
225 return globalFactory;
228bool Factory::isMimeTypeAvailable(
const QString &mimeType)
230#ifndef QT_NO_PHONON_PLATFORMPLUGIN
231 PlatformPlugin *f = globalFactory->platformPlugin();
233 return f->isMimeTypeAvailable(mimeType);
241void Factory::registerFrontendObject(MediaNodePrivate *bp)
243 globalFactory->mediaNodePrivateList.prepend(bp);
246void Factory::deregisterFrontendObject(MediaNodePrivate *bp)
250 if (!globalFactory.isDestroyed()) {
251 globalFactory->mediaNodePrivateList.removeAll(bp);
262void FactoryPrivate::objectDestroyed(
QObject * obj)
265 objects.removeAll(obj);
268#define FACTORY_IMPL(classname) \
269QObject *Factory::create ## classname(QObject *parent) \
272 return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent)); \
276#define FACTORY_IMPL_1ARG(classname) \
277QObject *Factory::create ## classname(int arg1, QObject *parent) \
280 return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent, QList<QVariant>() << arg1)); \
285FACTORY_IMPL(MediaObject)
286#ifndef QT_NO_PHONON_EFFECT
287FACTORY_IMPL_1ARG(Effect)
289#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
290FACTORY_IMPL(VolumeFaderEffect)
292FACTORY_IMPL(AudioOutput)
293#ifndef QT_NO_PHONON_VIDEO
294FACTORY_IMPL(VideoWidget)
296FACTORY_IMPL(VideoGraphicsObject)
298FACTORY_IMPL(AudioDataOutput)
302#ifndef QT_NO_PHONON_PLATFORMPLUGIN
303PlatformPlugin *FactoryPrivate::platformPlugin()
305 if (m_platformPlugin) {
306 return m_platformPlugin;
308 if (m_noPlatformPlugin) {
312 const QByteArray platform_plugin_env = qgetenv(
"PHONON_PLATFORMPLUGIN");
313 if (!platform_plugin_env.
isEmpty()) {
314 pDebug() << Q_FUNC_INFO <<
"platform plugin path:" << platform_plugin_env;
316 if (pluginLoader.load()) {
317 QObject *plInstance = pluginLoader.instance();
319 pDebug() << Q_FUNC_INFO <<
"unable to grab root component object for the platform plugin";
322 m_platformPlugin = qobject_cast<PlatformPlugin *>(plInstance);
323 if (m_platformPlugin) {
324 pDebug() << Q_FUNC_INFO <<
"platform plugin" << m_platformPlugin->applicationName();
325 return m_platformPlugin;
327 pDebug() << Q_FUNC_INFO <<
"platform plugin cast fail" << plInstance;
332 ensureLibraryPathSet();
342 for (
int i = 0; i < libPaths.
count(); ++i) {
343 const QString libPath = libPaths.
at(i) + suffix;
344 dir.setPath(libPath);
349 for (
int i = 0; i < files.
count(); ++i) {
350 pDebug() <<
"attempting to load" << libPath + files.
at(i);
352 if (!pluginLoader.load()) {
353 pDebug() << Q_FUNC_INFO <<
" platform plugin load failed:"
354 << pluginLoader.errorString();
357 pDebug() << pluginLoader.instance();
358 QObject *qobj = pluginLoader.instance();
359 m_platformPlugin = qobject_cast<PlatformPlugin *>(qobj);
360 pDebug() << m_platformPlugin;
361 if (m_platformPlugin) {
362 connect(qobj, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
363 SLOT(objectDescriptionChanged(ObjectDescriptionType)));
364 return m_platformPlugin;
367 pDebug() << Q_FUNC_INFO <<
dir.absolutePath() <<
"exists but the platform plugin was not loadable:" << pluginLoader.errorString();
368 pluginLoader.unload();
377 pDebug() << Q_FUNC_INFO <<
"platform plugin could not be loaded";
378 m_noPlatformPlugin =
true;
382PlatformPlugin *Factory::platformPlugin()
384 return globalFactory->platformPlugin();
388QObject *Factory::backend(
bool createWhenNull)
390 if (globalFactory.isDestroyed()) {
393 if (createWhenNull && globalFactory->m_backendObject ==
nullptr) {
394 globalFactory->createBackend();
398 if (globalFactory->m_backendObject) {
399 emit globalFactory->backendChanged();
402 return globalFactory->m_backendObject;
405#ifndef QT_NO_PROPERTIES
406#define GET_STRING_PROPERTY(name) \
407QString Factory::name() \
409 if (globalFactory->m_backendObject) { \
410 return globalFactory->m_backendObject->property(#name).toString(); \
415GET_STRING_PROPERTY(identifier)
416GET_STRING_PROPERTY(backendName)
417GET_STRING_PROPERTY(backendComment)
418GET_STRING_PROPERTY(backendVersion)
419GET_STRING_PROPERTY(backendIcon)
420GET_STRING_PROPERTY(backendWebsite)
426 globalFactory->objects.append(o);
437 ensureLibraryPathSet();
440 QSettings settings(
"kde.org",
"libphonon");
441 const int size = settings.beginReadArray(
"Backends");
442 for (
int i = 0; i < size; ++i) {
443 settings.setArrayIndex(i);
444 iidPreference.
append(settings.value(
"iid").toString());
450 for (
const QString &path : paths) {
451 const QString libPath =
path + PHONON_BACKEND_DIR_SUFFIX;
454 pDebug() << Q_FUNC_INFO <<
dir.absolutePath() <<
"does not exist";
459 for (
const QString &plugin : plugins) {
460 Phonon::BackendDescriptor bd(libPath + plugin);
465 const auto index = iidPreference.
indexOf(bd.iid);
468 bd.weight = iidPreference.
size() - index;
473 std::sort(backendList.
rbegin(), backendList.
rend());
477 const QString backendEnv = qEnvironmentVariable(
"PHONON_BACKEND");
482 for (
int i = 0; i < backendList.
size(); ++i) {
483 const auto &backend = backendList.
at(i);
484 if (backendEnv == backend.pluginName) {
485 backendList.
move(i, 0);
495#include "factory.moc"
496#include "moc_factory_p.cpp"
QString path(const QString &relativePath)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QString dir(const QString &fileClass)
bool isEmpty() const const
void addLibraryPath(const QString &path)
QCoreApplication * instance()
QStringList libraryPaths()
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
qsizetype indexOf(const AT &value, qsizetype from) const const
bool isEmpty() const const
void move(qsizetype from, qsizetype to)
reverse_iterator rbegin()
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString fromLocal8Bit(QByteArrayView str)
bool isEmpty() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)