1 /*****************************************************************************
2 * VLC backend for the Phonon library *
3 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com> *
4 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com> *
5 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org> *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public *
9 * License as published by the Free Software Foundation; either *
10 * version 3 of the License, or (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15 * Lesser General Public License for more details. *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with this package; if not, write to the Free Software *
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
20 *****************************************************************************/
24 #include "audiooutput.h"
25 #include "mediaobject.h"
26 #include "videowidget.h"
27 #include "devicemanager.h"
28 #include "effectmanager.h"
31 #include "vlcloader.h"
32 #include "vlcmediaobject.h"
34 #include <QtCore/QSet>
35 #include <QtCore/QVariant>
36 #include <QtCore/QtPlugin>
38 Q_EXPORT_PLUGIN2(phonon_vlc, Phonon::VLC::Backend)
44 Backend::Backend(QObject *parent, const QVariantList &)
50 bool wasInit = vlcInit();
52 setProperty("identifier", QLatin1String("phonon_vlc"));
53 setProperty("backendName", QLatin1String("VLC"));
54 setProperty("backendComment", QLatin1String("VLC plugin for Phonon"));
55 setProperty("backendVersion", QLatin1String("0.1"));
56 setProperty("backendWebsite", QLatin1String("http://multimedia.kde.org/"));
58 // Check if we should enable debug output
59 QString debugLevelString = qgetenv("PHONON_VLC_DEBUG");
60 int debugLevel = debugLevelString.toInt();
61 if (debugLevel > 3) // 3 is maximum
63 m_debugLevel = (DebugLevel)debugLevel;
66 logMessage(QString("Using VLC version %0").arg(libvlc_get_version()));
68 qWarning("Phonon::VLC::vlcInit: Failed to initialize VLC");
71 m_deviceManager = new DeviceManager(this);
72 m_effectManager = new EffectManager(this);
80 QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
83 case MediaObjectClass:
84 return new VLCMediaObject(parent);
85 case VolumeFaderEffectClass:
86 // return new VolumeFaderEffect(parent);
87 logMessage("createObject() : VolumeFaderEffect not implemented");
89 case AudioOutputClass: {
90 AudioOutput *ao = new AudioOutput(this, parent);
91 m_audioOutputs.append(ao);
94 case AudioDataOutputClass:
95 // return new AudioDataOutput(parent);
96 logMessage("createObject() : AudioDataOutput not implemented");
98 case VisualizationClass:
99 // return new Visualization(parent);
100 logMessage("createObject() : Visualization not implemented");
102 case VideoDataOutputClass:
103 // return new VideoDataOutput(parent);
104 logMessage("createObject() : VideoDataOutput not implemented");
107 return new Effect(m_effectManager, args[0].toInt(), parent);
108 case VideoWidgetClass:
109 return new VideoWidget(qobject_cast<QWidget *>(parent));
111 logMessage("createObject() : Backend object not available");
116 bool Backend::supportsVideo() const
121 bool Backend::supportsOSD() const
126 bool Backend::supportsFourcc(quint32 fourcc) const
131 bool Backend::supportsSubtitles() const
136 QStringList Backend::availableMimeTypes() const
138 if (m_supportedMimeTypes.isEmpty()) {
139 const_cast<Backend *>(this)->m_supportedMimeTypes
140 << QLatin1String("application/ogg")
141 << QLatin1String("application/vnd.rn-realmedia")
142 << QLatin1String("application/x-annodex")
143 << QLatin1String("application/x-flash-video")
144 << QLatin1String("application/x-quicktimeplayer")
145 << QLatin1String("audio/168sv")
146 << QLatin1String("audio/8svx")
147 << QLatin1String("audio/aiff")
148 << QLatin1String("audio/basic")
149 << QLatin1String("audio/mp3")
150 << QLatin1String("audio/mp4")
151 << QLatin1String("audio/mpeg")
152 << QLatin1String("audio/mpeg2")
153 << QLatin1String("audio/mpeg3")
154 << QLatin1String("audio/vnd.rn-realaudio")
155 << QLatin1String("audio/wav")
156 << QLatin1String("audio/x-16sv")
157 << QLatin1String("audio/x-8svx")
158 << QLatin1String("audio/x-aiff")
159 << QLatin1String("audio/x-basic")
160 << QLatin1String("audio/x-m4a")
161 << QLatin1String("audio/x-mp3")
162 << QLatin1String("audio/x-mpeg")
163 << QLatin1String("audio/x-mpeg2")
164 << QLatin1String("audio/x-mpeg3")
165 << QLatin1String("audio/x-mpegurl")
166 << QLatin1String("audio/x-ms-wma")
167 << QLatin1String("audio/x-ogg")
168 << QLatin1String("audio/x-pn-aiff")
169 << QLatin1String("audio/x-pn-au")
170 << QLatin1String("audio/x-pn-realaudio-plugin")
171 << QLatin1String("audio/x-pn-wav")
172 << QLatin1String("audio/x-pn-windows-acm")
173 << QLatin1String("audio/x-real-audio")
174 << QLatin1String("audio/x-realaudio")
175 << QLatin1String("audio/x-speex+ogg")
176 << QLatin1String("audio/x-wav")
177 << QLatin1String("image/ilbm")
178 << QLatin1String("image/png")
179 << QLatin1String("image/x-ilbm")
180 << QLatin1String("image/x-png")
181 << QLatin1String("video/anim")
182 << QLatin1String("video/avi")
183 << QLatin1String("video/mkv")
184 << QLatin1String("video/mng")
185 << QLatin1String("video/mp4")
186 << QLatin1String("video/mpeg")
187 << QLatin1String("video/mpg")
188 << QLatin1String("video/msvideo")
189 << QLatin1String("video/quicktime")
190 << QLatin1String("video/x-anim")
191 << QLatin1String("video/x-flic")
192 << QLatin1String("video/x-mng")
193 << QLatin1String("video/x-mpeg")
194 << QLatin1String("video/x-ms-asf")
195 << QLatin1String("video/x-ms-wmv")
196 << QLatin1String("video/x-msvideo")
197 << QLatin1String("video/x-quicktime");
199 return m_supportedMimeTypes;
202 QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
207 case Phonon::AudioOutputDeviceType: {
208 QList<AudioDevice> deviceList = deviceManager()->audioOutputDevices();
209 for (int dev = 0 ; dev < deviceList.size() ; ++dev)
210 list.append(deviceList[dev].id);
214 case Phonon::EffectType: {
215 QList<EffectInfo*> effectList = effectManager()->effects();
216 for (int eff = 0; eff < effectList.size(); ++eff)
228 QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
230 QHash<QByteArray, QVariant> ret;
233 case Phonon::AudioOutputDeviceType: {
234 QList<AudioDevice> audioDevices = deviceManager()->audioOutputDevices();
235 if (index >= 0 && index < audioDevices.size()) {
236 ret.insert("name", audioDevices[index].vlcId);
237 ret.insert("description", audioDevices[index].description);
238 ret.insert("icon", QLatin1String("audio-card"));
242 case Phonon::EffectType: {
243 QList<EffectInfo*> effectList = effectManager()->effects();
244 if (index >= 0 && index <= effectList.size()) {
245 const EffectInfo *effect = effectList[ index ];
246 ret.insert("name", effect->name());
247 ret.insert("description", effect->description());
248 ret.insert("author", effect->author());
250 Q_ASSERT(1); // Since we use list position as ID, this should not happen
261 bool Backend::startConnectionChange(QSet<QObject *> objects)
263 foreach(QObject *object, objects) {
264 logMessage(QString("Object: %0").arg(object->metaObject()->className()));
267 // There is nothing we can do but hope the connection changes will not take too long
268 // so that buffers would underrun
269 // But we should be pretty safe the way xine works by not doing anything here.
273 bool Backend::connectNodes(QObject *source, QObject *sink)
275 logMessage(QString("Backend connected %0 to %1")
276 .arg(source->metaObject()->className())
277 .arg(sink->metaObject()->className()));
280 // source = Phonon::VLC_MPlayer::MediaObject
281 // sink = Phonon::VLC_MPlayer::VideoWidget
284 // source = Phonon::VLC_MPlayer::MediaObject
285 // sink = Phonon::VLC_MPlayer::AudioOutput
288 // source = Phonon::VLC_MPlayer::MediaObject
289 // sink = Phonon::VLC_MPlayer::Effect
292 // source = Phonon::VLC_MPlayer::Effect
293 // sink = Phonon::VLC_MPlayer::AudioOutput
295 SinkNode *sinkNode = qobject_cast<SinkNode *>(sink);
297 PrivateMediaObject *mediaObject = qobject_cast<PrivateMediaObject *>(source);
299 // Connect the SinkNode to a MediaObject
300 sinkNode->connectToMediaObject(mediaObject);
303 // FIXME try to find a better way...
304 // Effect *effect = qobject_cast<Effect *>(source);
309 logMessage(QString("Linking %0 to %1 failed")
310 .arg(source->metaObject()->className())
311 .arg(sink->metaObject()->className()),
317 bool Backend::disconnectNodes(QObject *source, QObject *sink)
319 SinkNode *sinkNode = qobject_cast<SinkNode *>(sink);
321 PrivateMediaObject *mediaObject = qobject_cast<PrivateMediaObject *>(source);
323 // Disconnect the SinkNode from a MediaObject
324 sinkNode->disconnectFromMediaObject(mediaObject);
327 // FIXME try to find a better way...
328 // Effect *effect = qobject_cast<Effect *>(source);
336 bool Backend::endConnectionChange(QSet<QObject *> objects)
338 foreach(QObject *object, objects) {
339 logMessage(QString("Object: %0").arg(object->metaObject()->className()));
345 DeviceManager* Backend::deviceManager() const
347 return m_deviceManager;
350 EffectManager* Backend::effectManager() const
352 return m_effectManager;
356 * Return a debuglevel that is determined by the
357 * PHONON_VLC_DEBUG environment variable.
359 * Warning - important warnings
360 * Info - general info
361 * Debug - gives extra info
363 Backend::DebugLevel Backend::debugLevel() const
369 * Print a conditional debug message based on the current debug level
370 * If obj is provided, classname and objectname will be printed as well
374 void Backend::logMessage(const QString &message, int priority, QObject *obj) const
376 if (debugLevel() > 0) {
379 // Strip away namespace from className
380 QString className(obj->metaObject()->className());
381 int nameLength = className.length() - className.lastIndexOf(':') - 1;
382 className = className.right(nameLength);
383 output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
384 obj->objectName().toLatin1().constData(),
385 className.toLatin1().constData(), obj);
389 if (priority <= (int)debugLevel()) {
390 qDebug() << QString("PVLC(%1): %2").arg(priority).arg(output);
396 } // Namespace Phonon::VLC