Do not set any VLC interface
[phonon:phonon-vlc.git] / vlc / vlcloader.cpp
1 /*****************************************************************************
2  * libVLC backend for the Phonon library                                     *
3  *                                                                           *
4  * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
5  * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
6  * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
7  * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
8  *                                                                           *
9  * This program is free software; you can redistribute it and/or             *
10  * modify it under the terms of the GNU Lesser General Public                *
11  * License as published by the Free Software Foundation; either              *
12  * version 2.1 of the License, or (at your option) any later version.        *
13  *                                                                           *
14  * This program is distributed in the hope that it will be useful,           *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
17  * Lesser General Public License for more details.                           *
18  *                                                                           *
19  * You should have received a copy of the GNU Lesser General Public          *
20  * License along with this package; if not, write to the Free Software       *
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
22  *****************************************************************************/
23
24 #include "vlcloader.h"
25
26 #include <QtCore/QDebug>
27 #include <QtCore/QDir>
28 #include <QtCore/QFile>
29 #include <QtCore/QLibrary>
30 #include <QtCore/QSettings>
31 #include <QtCore/QString>
32 #include <QtCore/QStringList>
33 #include <QtCore/QCoreApplication>
34
35 // Global variables
36 libvlc_instance_t *vlc_instance = 0;
37
38 namespace Phonon
39 {
40 namespace VLC
41 {
42
43 bool vlcInit(int debugLevl)
44 {
45     // Global variables
46     vlc_instance = 0;
47
48     QString path = vlcPath();
49     if (!path.isEmpty()) {
50         QString pluginsPath = QString("--plugin-path=") + QDir::toNativeSeparators(QFileInfo(vlcPath()).dir().path());
51
52 #if defined(Q_OS_UNIX)
53         pluginsPath.append("/vlc");
54 #elif defined(Q_OS_WIN)
55         pluginsPath.append("\\plugins");
56 #endif
57         QByteArray p = QFile::encodeName(path);
58         QByteArray pp = QFile::encodeName(pluginsPath);
59
60         QByteArray log;
61         QByteArray logFile;
62         QByteArray verboseLevl;
63         if (debugLevl > 0) {
64             verboseLevl = QString("--verbose=").append(QString::number(debugLevl)).toLatin1();
65             log = "--extraintf=logger";
66             logFile = "--logfile=";
67 #ifdef Q_WS_WIN
68             QDir logFilePath(QString(qgetenv("APPDATA")).append("/vlc"));
69 #else
70             QDir logFilePath(QDir::homePath().append("/.vlc"));
71 #endif //Q_WS_WIN
72             logFilePath.mkdir("log");
73             logFile.append(QFile::encodeName(QDir::toNativeSeparators(logFilePath.path().append("/log/vlc-log-").append(QString::number(qApp->applicationPid())).append(".txt"))));
74         }
75         // VLC command line options. See vlc --full-help
76         const char *vlcArgs[] = {
77             p.constData(),
78             pp.constData(),
79             log.constData(),
80             logFile.constData(),
81             verboseLevl.constData(),
82             "--reset-plugins-cache",
83             "--no-media-library",
84 #ifndef Q_OS_MAC
85             "--no-one-instance",
86 #endif
87             "--no-osd",
88             "--no-stats",
89             "--no-video-title-show",
90             "--album-art=0"
91         };
92
93         // Create and initialize a libvlc instance (it should be done only once)
94         vlc_instance = libvlc_new(sizeof(vlcArgs) / sizeof(*vlcArgs), vlcArgs);
95         if (!vlc_instance) {
96             qDebug() << "libvlc exception:" << libvlc_errmsg();
97         }
98
99         return true;
100     }
101
102     return false;
103 }
104
105 void vlcRelease()
106 {
107     libvlc_release(vlc_instance);
108     vlcUnload();
109 }
110
111 #if defined(Q_OS_UNIX)
112 static bool libGreaterThan(const QString &lhs, const QString &rhs)
113 {
114     const QStringList lhsparts = lhs.split(QLatin1Char('.'));
115     const QStringList rhsparts = rhs.split(QLatin1Char('.'));
116     Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);
117
118     for (int i = 1; i < rhsparts.count(); ++i) {
119         if (lhsparts.count() <= i)
120             // left hand side is shorter, so it's less than rhs
121         {
122             return false;
123         }
124
125         bool ok = false;
126         int b = 0;
127         int a = lhsparts.at(i).toInt(&ok);
128         if (ok) {
129             b = rhsparts.at(i).toInt(&ok);
130         }
131         if (ok) {
132             // both toInt succeeded
133             if (a == b) {
134                 continue;
135             }
136             return a > b;
137         } else {
138             // compare as strings;
139             if (lhsparts.at(i) == rhsparts.at(i)) {
140                 continue;
141             }
142             return lhsparts.at(i) > rhsparts.at(i);
143         }
144     }
145
146     // they compared strictly equally so far
147     // lhs cannot be less than rhs
148     return true;
149 }
150 #endif
151
152 static QStringList findAllLibVlc()
153 {
154     QStringList paths;
155
156 #ifdef Q_OS_UNIX
157     paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
158             .split(QLatin1Char(':'), QString::SkipEmptyParts);
159     paths << QLatin1String(PHONON_LIB_INSTALL_DIR) << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
160
161 #if defined(Q_WS_MAC)
162     paths
163             << QCoreApplication::applicationDirPath()
164             << QCoreApplication::applicationDirPath() + QLatin1String("/../Frameworks")
165             << QCoreApplication::applicationDirPath() + QLatin1String("/../PlugIns")
166             << QCoreApplication::applicationDirPath() + QLatin1String("/lib")
167
168             ;
169 #endif
170
171     QStringList foundVlcs;
172     foreach(const QString & path, paths) {
173         QDir dir = QDir(path);
174         QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.*"), QDir::Files);
175
176         qSort(entryList.begin(), entryList.end(), libGreaterThan);
177         foreach(const QString & entry, entryList) {
178             if (entry.contains(".debug")) {
179                 continue;
180             }
181             foundVlcs << path + QLatin1Char('/') + entry;
182         }
183     }
184
185     return foundVlcs;
186 #elif defined(Q_OS_WIN)
187     // Read VLC version and installation directory from Windows registry
188     QSettings settings(QSettings::SystemScope, "VideoLAN", "VLC");
189     QString vlcVersion = settings.value("Version").toString();
190     QString vlcInstallDir = settings.value("InstallDir").toString();
191     if (vlcVersion.startsWith("1.1") && !vlcInstallDir.isEmpty()) {
192         paths << vlcInstallDir + QLatin1Char('\\') + "libvlc.dll";
193         return paths;
194     } else {
195         //If nothing is found in the registry try %PATH%
196         QStringList searchPaths = QString::fromLatin1(qgetenv("PATH"))
197                                   .split(QLatin1Char(';'), QString::SkipEmptyParts);
198         //search also in the application dir
199         searchPaths.append(QCoreApplication::applicationDirPath());
200
201         QStringList foundVlcs;
202         foreach(const QString & sp, searchPaths) {
203             QDir dir = QDir(sp);
204             QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.dll"), QDir::Files);
205             foreach(const QString & entry, entryList){
206                 foundVlcs << sp + QLatin1Char('\\') + entry;
207             }
208         }
209         paths << foundVlcs;
210         return paths;
211     }
212 #endif
213 }
214
215 static QLibrary *vlcLibrary = 0;
216
217 QString vlcPath()
218 {
219     static QString path;
220     if (!path.isEmpty()) {
221         return path;
222     }
223
224     vlcLibrary = new QLibrary();
225     QStringList paths = findAllLibVlc();
226     foreach(path, paths) {
227         vlcLibrary->setFileName(path);
228
229         if (!vlcLibrary->resolve("libvlc_exception_init")) { //"libvlc_exception_init" not contained in 1.1+
230             return path;
231         } else {
232             qDebug("Cannot resolve the symbol or load VLC library");
233         }
234         qWarning() << vlcLibrary->errorString();
235     }
236
237     vlcUnload();
238
239     return QString();
240 }
241
242 void vlcUnload()
243 {
244     vlcLibrary->unload();
245     delete vlcLibrary;
246     vlcLibrary = 0;
247 }
248
249 }
250 } // Namespace Phonon::VLC