diff -r e4ebb16b39ea -r 603d3f8b6302 src/multimedia/qmediapluginloader.cpp --- a/src/multimedia/qmediapluginloader.cpp Fri Sep 17 08:34:34 2010 +0300 +++ b/src/multimedia/qmediapluginloader.cpp Mon Oct 04 01:37:06 2010 +0300 @@ -46,17 +46,70 @@ #include #include "qmediaserviceproviderplugin.h" -#include "qmobilitypluginsearch.h" + +#if defined(Q_OS_SYMBIAN) +# include +#endif + +#if defined(Q_OS_MAC) +# include +#endif QT_BEGIN_NAMESPACE typedef QMap ObjectListMap; Q_GLOBAL_STATIC(ObjectListMap, staticMediaPlugins); + +#if defined(Q_OS_SYMBIAN) +// XXX: Copied over from Mobility, hopefully to be removed at some point +class DirChecker +{ +public: + DirChecker(); + ~DirChecker(); + bool checkDir(const QDir& dir); + +private: + RFs rfs; +}; + +DirChecker::DirChecker() +{ + qt_symbian_throwIfError(rfs.Connect()); +} + +bool DirChecker::checkDir(const QDir& dir) +{ + bool pathFound = false; + // In Symbian, going cdUp() in a c:/private// will result in *platsec* error at fileserver (requires AllFiles capability) + // Also, trying to cd() to a nonexistent directory causes *platsec* error. This does not cause functional harm, but should + // nevertheless be changed to use native Symbian methods to avoid unnecessary platsec warnings (as per qpluginloader.cpp). + // Use native Symbian code to check for directory existence, because checking + // for files from under non-existent protected dir like E:/private/ using + // QDir::exists causes platform security violations on most apps. + QString nativePath = QDir::toNativeSeparators(dir.absolutePath()); + TPtrC ptr = TPtrC16(static_cast(nativePath.utf16()), nativePath.length()); + TUint attributes; + TInt err = rfs.Att(ptr, attributes); + if (err == KErrNone) { + // yes, the directory exists. + pathFound = true; + } + return pathFound; +} + +DirChecker::~DirChecker() +{ + rfs.Close(); +} +#endif + + QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity): m_iid(iid) { - m_location = location + "/"; + m_location = QString::fromLatin1("/%1").arg(location); load(); } @@ -78,7 +131,83 @@ //to be used for testing purposes only void QMediaPluginLoader::setStaticPlugins(const QString &location, const QObjectList& objects) { - staticMediaPlugins()->insert(location+"/", objects); + staticMediaPlugins()->insert(QString::fromLatin1("/%1").arg(location), objects); +} + +QStringList QMediaPluginLoader::availablePlugins() const +{ + QStringList paths; + QStringList plugins; + +#if defined(Q_OS_SYMBIAN) + DirChecker dirChecker; +#endif + +#if defined(Q_OS_MAC) + QString imageSuffix(qgetenv("DYLD_IMAGE_SUFFIX")); + + // Bundle plugin directory + CFBundleRef mainBundle = CFBundleGetMainBundle(); + if (mainBundle != 0) { + CFURLRef baseUrl = CFBundleCopyBundleURL(mainBundle); + CFURLRef pluginUrlPart = CFBundleCopyBuiltInPlugInsURL(mainBundle); + CFStringRef pluginPathPart = CFURLCopyFileSystemPath(pluginUrlPart, kCFURLPOSIXPathStyle); + CFURLRef pluginUrl = CFURLCreateCopyAppendingPathComponent(0, baseUrl, pluginPathPart, true); + CFStringRef pluginPath = CFURLCopyFileSystemPath(pluginUrl, kCFURLPOSIXPathStyle); + + CFIndex length = CFStringGetLength(pluginPath); + UniChar buffer[length]; + CFStringGetCharacters(pluginPath, CFRangeMake(0, length), buffer); + + paths << QString(reinterpret_cast(buffer), length); + + CFRelease(pluginPath); + CFRelease(pluginUrl); + CFRelease(pluginPathPart); + CFRelease(pluginUrlPart); + CFRelease(baseUrl); + } +#endif + +#ifdef QTM_PLUGIN_PATH + // Mobility's plugin directory + paths << QLatin1String(QTM_PLUGIN_PATH); +#endif + + // Qt paths + paths << QCoreApplication::libraryPaths(); + + foreach (const QString &path, paths) { + QDir typeDir(path + m_location); +#if defined(Q_OS_SYMBIAN) + if (dirChecker.checkDir(typeDir)) +#endif + { + foreach (const QString &file, typeDir.entryList(QDir::Files)) { +#if defined(Q_OS_MAC) + if (!imageSuffix.isEmpty()) { // Only add appropriate images + if (file.lastIndexOf(imageSuffix, -6) == -1) + continue; + } else { // Ignore any images with common suffixes + if (file.endsWith(QLatin1String("_debug.dylib")) || + file.endsWith(QLatin1String("_profile.dylib"))) + continue; + } +#elif defined(Q_OS_UNIX) + // Ignore separate debug files + if (file.endsWith(QLatin1String(".debug"))) + continue; +#elif defined(Q_OS_WIN) + // Ignore non-dlls + if (!file.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive)) + continue; +#endif + plugins << typeDir.absoluteFilePath(file); + } + } + } + + return plugins; } void QMediaPluginLoader::load() @@ -97,25 +226,27 @@ } } } else { - QStringList plugins = QTM_PREPEND_NAMESPACE(mobilityPlugins)(m_location); - for (int i=0; i < plugins.count(); i++) { - QPluginLoader loader(plugins.at(i)); + foreach (const QString &plugin, availablePlugins()) { + QPluginLoader loader(plugin); + QObject *o = loader.instance(); if (o != 0 && o->qt_metacast(m_iid) != 0) { QFactoryInterface* p = qobject_cast(o); if (p != 0) { - foreach (QString const &key, p->keys()) + foreach (const QString &key, p->keys()) m_instances.insertMulti(key, o); } continue; } else { - qWarning() << "QMediaPluginLoader: Failed to load plugin: " << plugins.at(i) << loader.errorString(); + qWarning() << "QMediaPluginLoader: Failed to load plugin: " << plugin << loader.errorString(); } + delete o; loader.unload(); } } } + QT_END_NAMESPACE