--- 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 <QtCore/qdebug.h>
#include "qmediaserviceproviderplugin.h"
-#include "qmobilitypluginsearch.h"
+
+#if defined(Q_OS_SYMBIAN)
+# include <f32file.h>
+#endif
+
+#if defined(Q_OS_MAC)
+# include <CoreFoundation/CoreFoundation.h>
+#endif
QT_BEGIN_NAMESPACE
typedef QMap<QString,QObjectList> 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/<uid3>/ 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/<uid> using
+ // QDir::exists causes platform security violations on most apps.
+ QString nativePath = QDir::toNativeSeparators(dir.absolutePath());
+ TPtrC ptr = TPtrC16(static_cast<const TUint16*>(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<const QChar *>(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<QFactoryInterface*>(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