diff options
Diffstat (limited to 'src/3rdparty/phonon/phonon')
114 files changed, 18201 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/phonon/.krazy b/src/3rdparty/phonon/phonon/.krazy new file mode 100644 index 0000000..f0ab4d5 --- /dev/null +++ b/src/3rdparty/phonon/phonon/.krazy @@ -0,0 +1,2 @@ +EXCLUDE qclasses +SKIP /DESIGN/ diff --git a/src/3rdparty/phonon/phonon/BUGS b/src/3rdparty/phonon/phonon/BUGS new file mode 100644 index 0000000..fb74e44 --- /dev/null +++ b/src/3rdparty/phonon/phonon/BUGS @@ -0,0 +1,9 @@ +When the backend changes there's a drop in the playback. When it's in +PlayingState it could time how long it takes until the playback resumes and add +that time to the seek. + +When the backend changes the paths are not restored correctly and it crashes + +When a new AudioOutput is created with the same name and category it'll still cause +a notification if a device fallback was necessary. One such notification per +name/category or even ignoring the name sure is enough. diff --git a/src/3rdparty/phonon/phonon/CMakeLists.txt b/src/3rdparty/phonon/phonon/CMakeLists.txt new file mode 100644 index 0000000..ace934a --- /dev/null +++ b/src/3rdparty/phonon/phonon/CMakeLists.txt @@ -0,0 +1,139 @@ +if (PHONON_BUILD_TESTS) + add_subdirectory(tests) +endif (PHONON_BUILD_TESTS) + +if (PHONON_BUILD_EXAMPLES) + add_subdirectory(examples) +endif (PHONON_BUILD_EXAMPLES) + +add_subdirectory(experimental) + +set(PULSEAUDIO_MINIMUM_VERSION "0.9.15") +macro_optional_find_package(PulseAudio) +if (PULSEAUDIO_FOUND) + # PULSEAUDIO_DEVICE_MANAGER feature check could be moved to FindPulseAudio.cmake, hint hint. -- Rex + macro_ensure_version("0.9.21" "${PULSEAUDIO_VERSION}" PULSEAUDIO_DEVICE_MANAGER) +endif (PULSEAUDIO_FOUND) +macro_log_feature(PULSEAUDIO_FOUND "PulseAudio" "A cross-platform, networked sound server." "http://www.pulseaudio.org" FALSE "" "Allows audio playback via the PulseAudio soundserver when it is running") +macro_optional_find_package(GLIB2) +macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the pulseaudio for Phonon" "http://www.gtk.org/download/" FALSE) + + +if (GLIB2_FOUND AND PULSEAUDIO_FOUND) + add_definitions(-DHAVE_PULSEAUDIO) + include_directories(${GLIB2_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR}) + if (PULSEAUDIO_DEVICE_MANAGER) + add_definitions(-DHAVE_PULSEAUDIO_DEVICE_MANAGER) + endif(PULSEAUDIO_DEVICE_MANAGER) +else(GLIB2_FOUND AND PULSEAUDIO_FOUND) + set(PULSEAUDIO_INCLUDE_DIR "") + set(PULSEAUDIO_LIBRARY "") + set(PULSEAUDIO_MAINLOOP_LIBRARY "") +endif(GLIB2_FOUND AND PULSEAUDIO_FOUND) + + +set(phonon_LIB_SRCS + objectdescription.cpp + objectdescriptionmodel.cpp + phononnamespace.cpp + mediasource.cpp + abstractmediastream.cpp + streaminterface.cpp + mediaobject.cpp + medianode.cpp + path.cpp + effectparameter.cpp + effect.cpp + volumefadereffect.cpp + abstractaudiooutput.cpp + abstractaudiooutput_p.cpp + audiooutput.cpp + audiooutputinterface.cpp + abstractvideooutput.cpp + abstractvideooutput_p.cpp + backendcapabilities.cpp + globalconfig.cpp + factory.cpp + platform.cpp + mediacontroller.cpp + videowidget.cpp + videoplayer.cpp + seekslider.cpp + swiftslider.cpp + volumeslider.cpp + effectwidget.cpp + iodevicestream.cpp + audiodataoutput.cpp + pulsesupport.cpp + ) + +if (QT_QTDBUS_FOUND) + list(APPEND phonon_LIB_SRCS + audiooutputadaptor.cpp + ) +endif (QT_QTDBUS_FOUND) + + +add_definitions(-DPHONON_LIBRARY_PATH="${PLUGIN_INSTALL_DIR}/plugins") +automoc4_add_library(phonon SHARED ${phonon_LIB_SRCS}) +target_link_libraries(phonon ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) +if (GLIB2_FOUND AND PULSEAUDIO_FOUND) +target_link_libraries(phonon ${GLIB2_LIBRARIES} ${GOBJECT_LIBRARIES} ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY}) +endif (GLIB2_FOUND AND PULSEAUDIO_FOUND) + +if (QT_QTDBUS_FOUND) + target_link_libraries(phonon ${QT_QTDBUS_LIBRARY}) +endif (QT_QTDBUS_FOUND) +if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + # We need to explicitly link libm to phonon in Solaris + target_link_libraries(phonon m) +endif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + +set_target_properties(phonon PROPERTIES + VERSION ${PHONON_LIB_VERSION} + SOVERSION ${PHONON_LIB_SOVERSION} + DEFINE_SYMBOL MAKE_PHONON_LIB + ) +install(TARGETS phonon ${INSTALL_TARGETS_DEFAULT_ARGS}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/phononnamespace.h.in ${CMAKE_CURRENT_BINARY_DIR}/phononnamespace.h) + +install(FILES + phonon_export.h + objectdescription.h + objectdescriptionmodel.h + ${CMAKE_CURRENT_BINARY_DIR}/phononnamespace.h + mediasource.h + abstractmediastream.h + streaminterface.h + mediaobject.h + audiooutput.h + medianode.h + path.h + effectparameter.h + effect.h + effectinterface.h + volumefadereffect.h + volumefaderinterface.h + abstractaudiooutput.h + abstractvideooutput.h + backendcapabilities.h + phonondefs.h + backendinterface.h + mediaobjectinterface.h + audiooutputinterface.h + addoninterface.h + mediacontroller.h + videowidget.h + videowidgetinterface.h + videoplayer.h + seekslider.h + volumeslider.h + effectwidget.h + platformplugin.h + audiodataoutput.h + audiodataoutputinterface.h + globalconfig.h + pulsesupport.h + DESTINATION ${INCLUDE_INSTALL_DIR}/phonon COMPONENT Devel) + +install(FILES org.kde.Phonon.AudioOutput.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR}) diff --git a/src/3rdparty/phonon/phonon/IDEAS b/src/3rdparty/phonon/phonon/IDEAS new file mode 100644 index 0000000..96fe056 --- /dev/null +++ b/src/3rdparty/phonon/phonon/IDEAS @@ -0,0 +1,70 @@ +MediaInfo class +=============== + +It might be nice to have a class that gives information about MediaSource +objects without having to use MediaObject for it. Something like QFileInfo for +QFile. MediaObject could also return a list of MediaInfo objects for all the +MediaSource objects in the queue. + +Rationale: The app then can get info about length and substreams so that it can +set up everything correctly for the next "file" in the queue. + + +- on hotplug of a USB audio/video device: + 1. If the device is plugged in for the first time + Check whether the backend now provides new device selections. If yes, open + up central config with the page that allows selection of the default + devices. Tell the user what new options are available. + Allow the user to set preference of devices: If device USB-Headset is + available use that, else use builtin speakers. + + device info persistance +========================= +On device selections: should the user be presented with options that are +currently not available? It might actually be confusing to select a device that +is not usable at the moment. + +Some situations: +(device A is always available) +- user plugs device B +- selects device B as default +next day: device B unplugged +- phonon falls back to device A as B is not available and shows a passive popup + informing the user about the fallback +- user opens config dialog +- device B still shows up as default +- selects device A, closes dialog +- opens dialog again +- device B is gone... +- user plugs device B +- device B reappears + +The Backend has to provide the information about devices. Those can map directly +to hardware or a soundserver or some other virtual device. The Backend has to +have some unique identifier. For example the ALSA devices could be identified +using the ALSA device names (either hw:0, hw:1 or aliases from asoundrc). OSS +devices could be identified using /dev/dsp, /dev/dsp1 and so on. +=> the backend internal uid is a string +In the Frontend all that is needed is a name and a description of the device +(both translated to the current locale) and a unique identifier to talk to the +backend. This identifier could be the same as used internally by the Backend, +but doesn't have to be. + + "lowlevel" audio I/O +====================== +ByteStream is a buffered stream, and as therefore completely useless for cases +where an application wants to write audio data to the soundcard/-system with low +latency. +=> PcmInStream and PcmOutStream + + +============================================================================ += Ideas for "useless but nice" things (until somebody can convince me that = += they're useful) = +============================================================================ + + Video Output +============== +Add another VideoOutput that can be used directly with QGraphicsView by creating +a QGraphicsItem subclass. + diff --git a/src/3rdparty/phonon/phonon/Messages.sh b/src/3rdparty/phonon/phonon/Messages.sh new file mode 100644 index 0000000..c628a04 --- /dev/null +++ b/src/3rdparty/phonon/phonon/Messages.sh @@ -0,0 +1,6 @@ +#! /usr/bin/env bash +find ./ -maxdepth 1 -name "*.cpp" -print > files +find ./ -maxdepth 1 -name "*.h" -print >> files +#$EXTRACTRC `find $dirs -maxdepth 1 \( -name \*.rc -o -name \*.ui -o -name \*.ui3 -o -name \*.ui4 -o -name \*.kcfg \) ` >> rc.cpp || exit 11 +$XGETTEXT_QT --copyright-holder=This_file_is_part_of_KDE --msgid-bugs-address=http://bugs.kde.org --files-from=files -o $podir/libphonon.pot +rm files diff --git a/src/3rdparty/phonon/phonon/TODO b/src/3rdparty/phonon/phonon/TODO new file mode 100644 index 0000000..479bbd7 --- /dev/null +++ b/src/3rdparty/phonon/phonon/TODO @@ -0,0 +1,31 @@ +- add a metadata function that returns a QVariant instead of a QString - useful for QImage or other binary (QByteArray) content + +- QImage VideoWidget::screenshot(): ordinary screenshot doesn't work with XV says Christoph. And VideoDataOutput + would be major overkill. + +- consider whether to add a signal to notify when the information for + availableAudioStreams/availableVideoStreams/availableSubtitleStreams + is available + +- look at collaboration with other projects, e.g. pavucontrol, gsmartmix + +- consider Player dbus interface in MediaObject + +- add global setting to pause video when it's not visible + +- add a way to request a specific version (>=) from the Backend, so that known to be buggy Backends aren't used + +- Video Overlays (OSD) like: show a rectangle as a play symbol, show the position in + the file as something like [IIIIIIIII------], and so on + +- http://bugs.kde.org/show_bug.cgi?id=147494 + +- frame/sample precise positioning (cue in/out) + +- different timecode support like SMPTE + +- Codec interface - at least for audio + +- Speed factor for playback (useful mostly for audio - but video still needs to stay in sync) + +- tell the platform plugin which backend was loaded (if it doesn't do it itself) so that it can load KDE translations for the backend diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp b/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp new file mode 100644 index 0000000..bce7c11 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp @@ -0,0 +1,50 @@ +/* This file is part of the KDE project +Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "abstractaudiooutput.h" +#include "abstractaudiooutput_p.h" +#include "factory_p.h" + +#define PHONON_CLASSNAME AbstractAudioOutput + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + + AbstractAudioOutput::AbstractAudioOutput(AbstractAudioOutputPrivate &dd, QObject *parent) : QObject(parent), + MediaNode(dd) + { + } + + AbstractAudioOutput::~AbstractAudioOutput() + { + } + +} //namespace Phonon + +QT_END_NAMESPACE + +#undef PHONON_CLASSNAME + +#include "moc_abstractaudiooutput.cpp" + +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput.h b/src/3rdparty/phonon/phonon/abstractaudiooutput.h new file mode 100644 index 0000000..1045f18 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput.h @@ -0,0 +1,57 @@ +/* This file is part of the KDE project +Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#ifndef Phonon_ABSTRACTAUDIOOUTPUTBASE_H +#define Phonon_ABSTRACTAUDIOOUTPUTBASE_H + +#include "phonondefs.h" +#include "phonon_export.h" +#include "medianode.h" +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class AbstractAudioOutputPrivate; + + /** \class AbstractAudioOutput abstractaudiooutput.h Phonon/AbstractAudioOutput + * Common base class for all audio outputs. + * + * \see AudioOutput + */ + class PHONON_EXPORT AbstractAudioOutput : public QObject, public MediaNode + { + Q_OBJECT + K_DECLARE_PRIVATE(AbstractAudioOutput) + protected: + AbstractAudioOutput(AbstractAudioOutputPrivate &dd, QObject *parent); + public: + ~AbstractAudioOutput(); + }; +} //namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_ABSTRACTAUDIOOUTPUTBASE_H diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp new file mode 100644 index 0000000..20e0b3c --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp @@ -0,0 +1,44 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "abstractaudiooutput_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +bool AbstractAudioOutputPrivate::aboutToDeleteBackendObject() +{ + return true; +} + +void AbstractAudioOutputPrivate::setupBackendObject() +{ + Q_ASSERT(m_backendObject); + + // set up attributes +} + +} // namespace Phonon + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h new file mode 100644 index 0000000..9b3a57f --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_ABSTRACTAUDIOOUTPUT_P_H +#define PHONON_ABSTRACTAUDIOOUTPUT_P_H + +#include "abstractaudiooutput.h" +#include "medianode_p.h" +#include "phonondefs_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +class AbstractAudioOutputPrivate : public MediaNodePrivate +{ + Q_DECLARE_PUBLIC(AbstractAudioOutput) + PHONON_PRIVATEABSTRACTCLASS + public: + virtual QObject *qObject() { return q_func(); } + protected: + AbstractAudioOutputPrivate(CastId castId = AbstractAudioOutputPrivateType) + : MediaNodePrivate(castId) + { + } +}; +} //namespace Phonon + +QT_END_NAMESPACE + +#endif // PHONON_ABSTRACTAUDIOOUTPUT_P_H diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.cpp b/src/3rdparty/phonon/phonon/abstractmediastream.cpp new file mode 100644 index 0000000..f4a7db6 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractmediastream.cpp @@ -0,0 +1,197 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "abstractmediastream.h" +#include "abstractmediastream_p.h" +#include "mediaobjectinterface.h" +#include "mediaobject_p.h" +#include "streaminterface_p.h" + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +AbstractMediaStream::AbstractMediaStream(QObject *parent) + : QObject(parent), + d_ptr(new AbstractMediaStreamPrivate) +{ + d_ptr->q_ptr = this; +} + +AbstractMediaStream::AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject *parent) + : QObject(parent), + d_ptr(&dd) +{ + d_ptr->q_ptr = this; +} + +AbstractMediaStream::~AbstractMediaStream() +{ +} + +qint64 AbstractMediaStream::streamSize() const +{ + return d_ptr->streamSize; +} + +void AbstractMediaStream::setStreamSize(qint64 newSize) +{ + d_ptr->setStreamSize(newSize); +} + +void AbstractMediaStreamPrivate::setStreamSize(qint64 newSize) +{ + streamSize = newSize; + if (streamInterface) { + streamInterface->setStreamSize(newSize); + } +} + +bool AbstractMediaStream::streamSeekable() const +{ + return d_ptr->streamSeekable; +} + +void AbstractMediaStream::setStreamSeekable(bool s) +{ + d_ptr->setStreamSeekable(s); +} + +void AbstractMediaStreamPrivate::setStreamSeekable(bool s) +{ + streamSeekable = s; + if (streamInterface) { + streamInterface->setStreamSeekable(s); + } +} + +void AbstractMediaStream::writeData(const QByteArray &data) +{ + d_ptr->writeData(data); +} + +void AbstractMediaStreamPrivate::writeData(const QByteArray &data) +{ + if (ignoreWrites) { + return; + } + Q_ASSERT(streamInterface); + streamInterface->writeData(data); +} + +void AbstractMediaStream::endOfData() +{ + d_ptr->endOfData(); +} + +void AbstractMediaStreamPrivate::endOfData() +{ + if (streamInterface) { + streamInterface->endOfData(); + } +} + +void AbstractMediaStream::error(Phonon::ErrorType type, const QString &text) +{ + Q_D(AbstractMediaStream); + d->errorType = type; + d->errorText = text; + if (d->mediaObjectPrivate) { + // TODO: MediaObject might be in a different thread + d->mediaObjectPrivate->streamError(type, text); + } +} + +void AbstractMediaStream::enoughData() +{ +} + +void AbstractMediaStream::seekStream(qint64) +{ + Q_ASSERT(!d_ptr->streamSeekable); +} + +AbstractMediaStreamPrivate::~AbstractMediaStreamPrivate() +{ + if (mediaObjectPrivate) { + // TODO: MediaObject might be in a different thread + mediaObjectPrivate->removeDestructionHandler(this); + } + if (streamInterface) { + // TODO: StreamInterface might be in a different thread + streamInterface->d->disconnectMediaStream(); + } +} + +void AbstractMediaStreamPrivate::setStreamInterface(StreamInterface *iface) +{ + Q_Q(AbstractMediaStream); + streamInterface = iface; + if (!iface) { + // our subclass might be just about to call writeData, so tell it we have enoughData and + // ignore the next writeData calls + q->enoughData(); + ignoreWrites = true; + return; + } + if (ignoreWrites) { + ignoreWrites = false; + // we had a StreamInterface before. The new StreamInterface expects us to start reading from + // position 0 + q->reset(); + } else { + iface->setStreamSize(streamSize); + iface->setStreamSeekable(streamSeekable); + } +} + +void AbstractMediaStreamPrivate::setMediaObjectPrivate(MediaObjectPrivate *mop) +{ + // TODO: MediaObject might be in a different thread + mediaObjectPrivate = mop; + mediaObjectPrivate->addDestructionHandler(this); + if (!errorText.isEmpty()) { + mediaObjectPrivate->streamError(errorType, errorText); + } +} + +void AbstractMediaStreamPrivate::phononObjectDestroyed(MediaNodePrivate *bp) +{ + // TODO: MediaObject might be in a different thread + Q_ASSERT(bp == mediaObjectPrivate); + Q_UNUSED(bp); + mediaObjectPrivate = 0; +} + +} // namespace Phonon + + +QT_END_NAMESPACE + +#include "moc_abstractmediastream.cpp" + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.h b/src/3rdparty/phonon/phonon/abstractmediastream.h new file mode 100644 index 0000000..87fa140 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractmediastream.h @@ -0,0 +1,227 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_ABSTRACTMEDIASTREAM_H +#define PHONON_ABSTRACTMEDIASTREAM_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QByteArray; + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +namespace Phonon +{ +class MediaObject; +class AbstractMediaStreamPrivate; + +/** \class AbstractMediaStream abstractmediastream.h Phonon/AbstractMediaStream + * \brief Base class for custom media data streams. + * + * Implement this class to provide a custom data stream to the backend. The class supports both, the + * push and the pull model. + * + * Push: + * \code + * PushStream::PushStream(QObject *parent) + * : AbstractMediaStream(parent), m_timer(new QTimer(this)) + * { + * setStreamSize(getMediaStreamSize()); + * + * connect(m_timer, SIGNAL(timeout()), SLOT(moreData())); + * m_timer->setInterval(0); + * } + * + * void PushStream::moreData() + * { + * const QByteArray data = getMediaData(); + * if (data.isEmpty()) { + * endOfData(); + * } else { + * writeData(data); + * } + * } + * + * void PushStream::needData() + * { + * m_timer->start(); + * moreData(); + * } + * + * void PushStream::enoughData() + * { + * m_timer->stop(); + * } + * \endcode + * + * Pull: + * \code + * PullStream::PullStream(QObject *parent) + * : AbstractMediaStream(parent) + * { + * setStreamSize(getMediaStreamSize()); + * } + * + * void PullStream::needData() + * { + * const QByteArray data = getMediaData(); + * if (data.isEmpty()) { + * endOfData(); + * } else { + * writeData(data); + * } + * } + * \endcode + * + * \ingroup Playback + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT AbstractMediaStream : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(AbstractMediaStream) + friend class MediaObject; + friend class MediaObjectPrivate; + friend class StreamInterface; + public: + virtual ~AbstractMediaStream(); + + protected: + /** + * Constructs an AbstractMediaStream object with a \p parent. + */ + explicit AbstractMediaStream(QObject *parent = 0); + + /** + * Returns the stream size that was set with \ref setStreamSize. + * + * A negative value means that the length of the stream cannot be known. + * + * Defaults to \c 0. + */ + qint64 streamSize() const; + + /** + * Sets the size of the stream in number of bytes. + * + * A negative value means that the length of the stream cannot be known. + * + * Defaults to 0. + * + * This function has to be called. A backend will not call \ref needData() until the + * stream size is set. + */ + void setStreamSize(qint64); + + /** + * Returns whether your data stream is set as seekable. + * + * Defaults to \c false. + */ + bool streamSeekable() const; + + /** + * Sets whether your data stream is seekable. + * + * Defaults to \c false. + * + * If you set this to \c true you have to implement the \ref seekStream function. + */ + void setStreamSeekable(bool); + + /** + * Sends the media \p data to the backend for decoding. + * + * \warning Don't call this function before the first needData() is emitted. + */ + void writeData(const QByteArray &data); + + /** + * Tells the backend that the media data stream is at its end. + * + * \warning Don't call this function before the first needData() is emitted. + */ + void endOfData(); + + /** + * If an I/O error occurs you should call this function to make MediaObject go into + * ErrorState. + * + * \see MediaObject::errorType() + * \see MediaObject::errorString() + */ + void error(Phonon::ErrorType errorType, const QString &errorString); + + /** + * Reimplement this function to reset the stream. Subsequent calls to writeData should start + * from the first position of the data unless a seek is requested. + * + * The function is necessary for the case where a non-seekable MediaStream is + * played more than once. For a seekable stream the implementation can simply call + * \code + * seekStream(0); + * \endcode. + */ + virtual void reset() = 0; + + /** + * Reimplement this function to be notified when the backend needs data. + * + * When this function is called you should try to call writeData or endOfData before + * returning. + */ + virtual void needData() = 0; + + /** + * Reimplement this function to be notified when the backend has enough data and your stream + * object may take a break. This method is important for pushing data to the backend in + * order to not fill the backend buffer unnecessarily. + */ + virtual void enoughData(); + + /** + * Reimplement this function if your stream is seekable. + * + * When this function is called the next call to writeData has to be at the requested \p + * offset. + * + * \warning Do not call the parent implementation. + */ + virtual void seekStream(qint64 offset); + + AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject *parent); + QScopedPointer<AbstractMediaStreamPrivate> d_ptr; +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_ABSTRACTMEDIASTREAM_H diff --git a/src/3rdparty/phonon/phonon/abstractmediastream_p.h b/src/3rdparty/phonon/phonon/abstractmediastream_p.h new file mode 100644 index 0000000..a676716 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractmediastream_p.h @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef ABSTRACTMEDIASTREAM_P_H +#define ABSTRACTMEDIASTREAM_P_H + +#include "phonon_export.h" +#include "abstractmediastream.h" +#include "mediaobject_p.h" +#include "streaminterface.h" + +#include "medianodedestructionhandler_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +class MediaObjectPrivate; + +namespace Phonon +{ +class PHONON_EXPORT AbstractMediaStreamPrivate : private MediaNodeDestructionHandler +{ + friend class MediaObject; + Q_DECLARE_PUBLIC(AbstractMediaStream) + public: + void setStreamInterface(StreamInterface *); + void setMediaObjectPrivate(MediaObjectPrivate *); + ~AbstractMediaStreamPrivate(); + + protected: + AbstractMediaStreamPrivate() + : streamSize(0), + streamSeekable(false), + ignoreWrites(false), + streamInterface(0), + mediaObjectPrivate(0), + errorType(NoError) + { + } + + virtual void setStreamSize(qint64 newSize); + virtual void setStreamSeekable(bool s); + virtual void writeData(const QByteArray &data); + virtual void endOfData(); + void phononObjectDestroyed(MediaNodePrivate *); + + AbstractMediaStream *q_ptr; + qint64 streamSize; + bool streamSeekable; + bool ignoreWrites; + StreamInterface *streamInterface; + MediaObjectPrivate *mediaObjectPrivate; + Phonon::ErrorType errorType; + QString errorText; +}; +} // namespace Phonon + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE + +#endif // ABSTRACTMEDIASTREAM_P_H +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput.cpp b/src/3rdparty/phonon/phonon/abstractvideooutput.cpp new file mode 100644 index 0000000..1695b78 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractvideooutput.cpp @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "abstractvideooutput.h" +#include "abstractvideooutput_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ + +AbstractVideoOutput::AbstractVideoOutput(AbstractVideoOutputPrivate &d) + : MediaNode(d) +{ +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput.h b/src/3rdparty/phonon/phonon/abstractvideooutput.h new file mode 100644 index 0000000..824f729 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractvideooutput.h @@ -0,0 +1,74 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#ifndef Phonon_ABSTRACTVIDEOOUTPUTBASE_H +#define Phonon_ABSTRACTVIDEOOUTPUTBASE_H + +#include "phonondefs.h" +#include "phonon_export.h" +#include "medianode.h" +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +class QString; + +namespace Phonon +{ + +namespace Experimental +{ + class Visualization; + class VisualizationPrivate; +} // namespace Experimental + + class AbstractVideoOutputPrivate; + + /** \class AbstractVideoOutput abstractvideooutput.h Phonon/AbstractVideoOutput + * \brief Common base class for all video outputs. + * + * \see VideoWidget + */ + class PHONON_EXPORT AbstractVideoOutput : public MediaNode + { + friend class Experimental::Visualization; + friend class Experimental::VisualizationPrivate; + K_DECLARE_PRIVATE(AbstractVideoOutput) + protected: + /** + * \internal + * Constructor that is called from derived classes. + * + * \param d the private object + */ + AbstractVideoOutput(AbstractVideoOutputPrivate &d); + }; +} //namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // Phonon_ABSTRACTVIDEOOUTPUTBASE_H diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp b/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp new file mode 100644 index 0000000..a9cfa4d --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "abstractvideooutput_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ + +bool AbstractVideoOutputPrivate::aboutToDeleteBackendObject() +{ + return true; +} + +} //namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput_p.h b/src/3rdparty/phonon/phonon/abstractvideooutput_p.h new file mode 100644 index 0000000..90230d4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/abstractvideooutput_p.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef ABSTRACTVIDEOOUTPUT_P_H +#define ABSTRACTVIDEOOUTPUT_P_H + +#include "abstractvideooutput.h" +#include "medianode_p.h" +#include "phonondefs_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ +class AbstractVideoOutputPrivate : public MediaNodePrivate +{ + Q_DECLARE_PUBLIC(AbstractVideoOutput) + PHONON_PRIVATEABSTRACTCLASS +}; +} //namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE + +#endif // ABSTRACTVIDEOOUTPUT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/addoninterface.h b/src/3rdparty/phonon/phonon/addoninterface.h new file mode 100644 index 0000000..229129b --- /dev/null +++ b/src/3rdparty/phonon/phonon/addoninterface.h @@ -0,0 +1,103 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_ADDONINTERFACE_H +#define PHONON_ADDONINTERFACE_H + +#include "phononnamespace.h" + +#include <QtCore/QList> +#include <QtCore/QVariant> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_MEDIACONTROLLER + +namespace Phonon +{ +/** \class AddonInterface addoninterface.h Phonon/AddonInterface + * \short Interface for Menu, Chapter, Angle and Title/Track control. + * + * \author Matthias Kretz <kretz@kde.org> + */ +class AddonInterface +{ + public: + virtual ~AddonInterface() {} + + enum Interface { + NavigationInterface = 1, + ChapterInterface = 2, + AngleInterface = 3, + TitleInterface = 4, + SubtitleInterface = 5, + AudioChannelInterface = 6 + }; + + enum NavigationCommand { + Menu1Button + }; + enum ChapterCommand { + availableChapters, + chapter, + setChapter + }; + enum AngleCommand { + availableAngles, + angle, + setAngle + }; + enum TitleCommand { + availableTitles, + title, + setTitle, + autoplayTitles, + setAutoplayTitles + }; + enum SubtitleCommand { + availableSubtitles, + currentSubtitle, + setCurrentSubtitle + }; + enum AudioChannelCommand { + availableAudioChannels, + currentAudioChannel, + setCurrentAudioChannel + }; + + virtual bool hasInterface(Interface iface) const = 0; + + virtual QVariant interfaceCall(Interface iface, int command, + const QList<QVariant> &arguments = QList<QVariant>()) = 0; +}; + +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::AddonInterface, "AddonInterface0.2.phonon.kde.org") + +#endif //QT_NO_PHONON_MEDIACONTROLLER + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_ADDONINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.cpp b/src/3rdparty/phonon/phonon/audiodataoutput.cpp new file mode 100644 index 0000000..fa8ec0d --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutput.cpp @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "audiodataoutput.h" +#include "audiodataoutput_p.h" +#include "factory_p.h" + +#define PHONON_CLASSNAME AudioDataOutput + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +PHONON_HEIR_IMPL(AbstractAudioOutput) + +PHONON_GETTER(int, dataSize, d->dataSize) +PHONON_GETTER(int, sampleRate, -1) +PHONON_SETTER(setDataSize, dataSize, int) + +bool AudioDataOutputPrivate::aboutToDeleteBackendObject() +{ + Q_ASSERT(m_backendObject); + pBACKEND_GET(int, dataSize, "dataSize"); + + return AbstractAudioOutputPrivate::aboutToDeleteBackendObject(); +} + +void AudioDataOutputPrivate::setupBackendObject() +{ + Q_Q(AudioDataOutput); + Q_ASSERT(m_backendObject); + AbstractAudioOutputPrivate::setupBackendObject(); + + // set up attributes + pBACKEND_CALL1("setDataSize", int, dataSize); + + qRegisterMetaType<QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > >("QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> >"); + + QObject::connect(m_backendObject, + SIGNAL(dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &)), + q, SIGNAL(dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &))); + QObject::connect(m_backendObject, SIGNAL(endOfMedia(int)), q, SIGNAL(endOfMedia(int))); +} + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.h b/src/3rdparty/phonon/phonon/audiodataoutput.h new file mode 100644 index 0000000..7a559b3 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutput.h @@ -0,0 +1,135 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#ifndef Phonon_AUDIODATAOUTPUT_H +#define Phonon_AUDIODATAOUTPUT_H + +#include "phonon_export.h" +#include "abstractaudiooutput.h" +#include "phonondefs.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template<typename T> class QVector; +template<typename Key, typename T> class QMap; +#endif + +namespace Phonon +{ + class AudioDataOutputPrivate; + + /** + * \short This class gives you the audio data (for visualizations). + * + * This class implements a special AbstractAudioOutput that gives your + * application the audio data. Don't expect realtime performance. But + * the latencies should be low enough to use the audio data for + * visualizations. You can also use the audio data for further processing + * (e.g. encoding and saving to a file). + * + * \author Matthias Kretz <kretz@kde.org> + */ + class PHONON_EXPORT AudioDataOutput : public AbstractAudioOutput + { + Q_OBJECT + K_DECLARE_PRIVATE(AudioDataOutput) + Q_ENUMS(Channel) + Q_PROPERTY(int dataSize READ dataSize WRITE setDataSize) + PHONON_HEIR(AudioDataOutput) + public: + /** + * Specifies the channel the audio data belongs to. + */ + enum Channel + { + LeftChannel, + RightChannel, + CenterChannel, + LeftSurroundChannel, + RightSurroundChannel, + SubwooferChannel + }; + + /** + * Returns the currently used number of samples passed through + * the signal. + * + * \see setDataSize + */ + int dataSize() const; + + /** + * Returns the sample rate in Hz. Common sample rates are 44100 Hz + * and 48000 Hz. AudioDataOutput will not do any sample rate + * conversion for you. If you need to convert the sample rate you + * might want to take a look at libsamplerate. For visualizations it + * is often enough to do simple interpolation or even drop/duplicate + * samples. + * + * \return The sample rate as reported by the backend. If the + * backend is unavailable -1 is returned. + */ + int sampleRate() const; + + public Q_SLOTS: + /** + * Sets the number of samples to be passed in one signal emission. + * + * Defaults to 512 samples per emitted signal. + * + * \param size the number of samples + */ + void setDataSize(int size); + + Q_SIGNALS: + /** + * Emitted whenever another dataSize number of samples are ready. + * + * \param data A mapping of Channel to a vector holding the audio data. + */ + void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &data); + + + /** + * This signal is emitted before the last dataReady signal of a + * media is emitted. + * + * If, for example, the playback of a media file has finished and the + * last audio data of that file is going to be passed with the next + * dataReady signal, and only the 28 first samples of the data + * vector are from that media file endOfMedia will be emitted right + * before dataReady with \p remainingSamples = 28. + * + * \param remainingSamples The number of samples in the next + * dataReady vector that belong to the media that was playing to + * this point. + */ + void endOfMedia(int remainingSamples); + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_AUDIODATAOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/audiodataoutput_p.h b/src/3rdparty/phonon/phonon/audiodataoutput_p.h new file mode 100644 index 0000000..5fd4f80 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutput_p.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef AUDIODATAOUTPUT_P_H +#define AUDIODATAOUTPUT_P_H + +#include "audiodataoutput.h" +#include "abstractaudiooutput_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +class AudioDataOutputPrivate : public AbstractAudioOutputPrivate +{ + Q_DECLARE_PUBLIC(AudioDataOutput) + PHONON_PRIVATECLASS + protected: + AudioDataOutputPrivate() + : dataSize(512) + { + } + + int dataSize; +}; + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // AUDIODATAOUTPUT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/audiodataoutputinterface.h b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h new file mode 100644 index 0000000..08bc7fc --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_AUDIODATAOUTPUTINTERFACE_H +#define PHONON_AUDIODATAOUTPUTINTERFACE_H + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +class AudioDataOutput; + +class AudioDataOutputInterface +{ + public: + virtual ~AudioDataOutputInterface() {} + + virtual AudioDataOutput *frontendObject() const = 0; + virtual void setFrontendObject(AudioDataOutput *) = 0; +}; + +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::AudioDataOutputInterface, "0AudioDataOutputInterface.phonon.kde.org") + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_AUDIODATAOUTPUTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp new file mode 100644 index 0000000..e94caad --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutput.cpp @@ -0,0 +1,511 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "audiooutput.h" +#include "audiooutput_p.h" +#include "factory_p.h" +#include "objectdescription.h" +#include "audiooutputadaptor_p.h" +#include "globalconfig.h" +#include "audiooutputinterface.h" +#include "phononnamespace_p.h" +#include "platform_p.h" +#include "pulsesupport.h" + +#include <QtCore/qmath.h> +#include <QtCore/quuid.h> + +#define PHONON_CLASSNAME AudioOutput +#define IFACES2 AudioOutputInterface42 +#define IFACES1 IFACES2 +#define IFACES0 AudioOutputInterface40, IFACES1 +#define PHONON_INTERFACENAME IFACES0 + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +static inline bool callSetOutputDevice(AudioOutputPrivate *const d, int index) +{ + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) + return pulse->setOutputDevice(d->getStreamUuid(), index); + + Iface<IFACES2> iface(d); + if (iface) { + return iface->setOutputDevice(AudioOutputDevice::fromIndex(index)); + } + return Iface<IFACES0>::cast(d)->setOutputDevice(index); +} + +static inline bool callSetOutputDevice(AudioOutputPrivate *const d, const AudioOutputDevice &dev) +{ + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) + return pulse->setOutputDevice(d->getStreamUuid(), dev.index()); + + Iface<IFACES2> iface(d); + if (iface) { + return iface->setOutputDevice(dev); + } + return Iface<IFACES0>::cast(d)->setOutputDevice(dev.index()); +} + +AudioOutput::AudioOutput(Phonon::Category category, QObject *parent) + : AbstractAudioOutput(*new AudioOutputPrivate, parent) +{ + K_D(AudioOutput); + d->init(category); +} + +AudioOutput::AudioOutput(QObject *parent) + : AbstractAudioOutput(*new AudioOutputPrivate, parent) +{ + K_D(AudioOutput); + d->init(NoCategory); +} + +void AudioOutputPrivate::init(Phonon::Category c) +{ + Q_Q(AudioOutput); +#ifndef QT_NO_DBUS + adaptor = new AudioOutputAdaptor(q); + static unsigned int number = 0; + const QString &path = QLatin1String("/AudioOutputs/") + QString::number(number++); + QDBusConnection con = QDBusConnection::sessionBus(); + con.registerObject(path, q); + emit adaptor->newOutputAvailable(con.baseService(), path); + q->connect(q, SIGNAL(volumeChanged(qreal)), adaptor, SIGNAL(volumeChanged(qreal))); + q->connect(q, SIGNAL(mutedChanged(bool)), adaptor, SIGNAL(mutedChanged(bool))); +#endif + + category = c; + streamUuid = QUuid::createUuid().toString(); + PulseSupport *pulse = PulseSupport::getInstance(); + pulse->setStreamPropList(category, streamUuid); + q->connect(pulse, SIGNAL(usingDevice(QString,int)), SLOT(_k_deviceChanged(QString,int))); + + createBackendObject(); + + q->connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(_k_deviceListChanged())); +} + +QString AudioOutputPrivate::getStreamUuid() +{ + return streamUuid; +} + +void AudioOutputPrivate::createBackendObject() +{ + if (m_backendObject) + return; + Q_Q(AudioOutput); + m_backendObject = Factory::createAudioOutput(q); + device = AudioOutputDevice::fromIndex(GlobalConfig().audioOutputDeviceFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices)); + if (m_backendObject) { + setupBackendObject(); + } +} + +QString AudioOutput::name() const +{ + K_D(const AudioOutput); + return d->name; +} + +void AudioOutput::setName(const QString &newName) +{ + K_D(AudioOutput); + if (d->name == newName) { + return; + } + d->name = newName; + setVolume(Platform::loadVolume(newName)); +#ifndef QT_NO_DBUS + if (d->adaptor) { + emit d->adaptor->nameChanged(newName); + } +#endif +} + +static const qreal LOUDNESS_TO_VOLTAGE_EXPONENT = qreal(0.67); +static const qreal VOLTAGE_TO_LOUDNESS_EXPONENT = qreal(1.0/LOUDNESS_TO_VOLTAGE_EXPONENT); + +void AudioOutput::setVolume(qreal volume) +{ + K_D(AudioOutput); + d->volume = volume; + if (k_ptr->backendObject() && !d->muted) { + // using Stevens' power law loudness is proportional to (sound pressure)^0.67 + // sound pressure is proportional to voltage: + // p² \prop P \prop V² + // => if a factor for loudness of x is requested + INTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT))); + } else { + emit volumeChanged(volume); + } + Platform::saveVolume(d->name, volume); +} + +qreal AudioOutput::volume() const +{ + K_D(const AudioOutput); + if (d->muted || !d->m_backendObject) { + return d->volume; + } + return pow(INTERFACE_CALL(volume()), LOUDNESS_TO_VOLTAGE_EXPONENT); +} + +#ifndef PHONON_LOG10OVER20 +#define PHONON_LOG10OVER20 +static const qreal log10over20 = qreal(0.1151292546497022842); // ln(10) / 20 +#endif // PHONON_LOG10OVER20 + +qreal AudioOutput::volumeDecibel() const +{ + K_D(const AudioOutput); + if (d->muted || !d->m_backendObject) { + return log(d->volume) / log10over20; + } + return 0.67 * log(INTERFACE_CALL(volume())) / log10over20; +} + +void AudioOutput::setVolumeDecibel(qreal newVolumeDecibel) +{ + setVolume(exp(newVolumeDecibel * log10over20)); +} + +bool AudioOutput::isMuted() const +{ + K_D(const AudioOutput); + return d->muted; +} + +void AudioOutput::setMuted(bool mute) +{ + K_D(AudioOutput); + if (d->muted != mute) { + if (mute) { + d->muted = mute; + if (k_ptr->backendObject()) { + INTERFACE_CALL(setVolume(0.0)); + } + } else { + if (k_ptr->backendObject()) { + INTERFACE_CALL(setVolume(pow(d->volume, VOLTAGE_TO_LOUDNESS_EXPONENT))); + } + d->muted = mute; + } + emit mutedChanged(mute); + } +} + +Category AudioOutput::category() const +{ + K_D(const AudioOutput); + return d->category; +} + +AudioOutputDevice AudioOutput::outputDevice() const +{ + K_D(const AudioOutput); + return d->device; +} + +bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice) +{ + K_D(AudioOutput); + if (!newAudioOutputDevice.isValid()) { + d->outputDeviceOverridden = d->forceMove = false; + const int newIndex = GlobalConfig().audioOutputDeviceFor(d->category); + if (newIndex == d->device.index()) { + return true; + } + d->device = AudioOutputDevice::fromIndex(newIndex); + } else { + d->outputDeviceOverridden = d->forceMove = true; + if (d->device == newAudioOutputDevice) { + return true; + } + d->device = newAudioOutputDevice; + } + if (k_ptr->backendObject()) { + return callSetOutputDevice(d, d->device.index()); + } + return true; +} + +bool AudioOutputPrivate::aboutToDeleteBackendObject() +{ + if (m_backendObject) { + volume = pINTERFACE_CALL(volume()); + } + return AbstractAudioOutputPrivate::aboutToDeleteBackendObject(); +} + +void AudioOutputPrivate::setupBackendObject() +{ + Q_Q(AudioOutput); + Q_ASSERT(m_backendObject); + AbstractAudioOutputPrivate::setupBackendObject(); + + QObject::connect(m_backendObject, SIGNAL(volumeChanged(qreal)), q, SLOT(_k_volumeChanged(qreal))); + QObject::connect(m_backendObject, SIGNAL(audioDeviceFailed()), q, SLOT(_k_audioDeviceFailed())); + + // set up attributes + pINTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT))); + +#ifndef QT_NO_PHONON_SETTINGSGROUP + // if the output device is not available and the device was not explicitly set + // There is no need to set the output device initially if PA is used as + // we know it will not work (stream doesn't exist yet) and that this will be + // handled by _k_deviceChanged() + if (!PulseSupport::getInstance()->isActive() && !callSetOutputDevice(this, device) && !outputDeviceOverridden) { + // fall back in the preference list of output devices + QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); + if (deviceList.isEmpty()) { + return; + } + for (int i = 0; i < deviceList.count(); ++i) { + const AudioOutputDevice &dev = AudioOutputDevice::fromIndex(deviceList.at(i)); + if (callSetOutputDevice(this, dev)) { + handleAutomaticDeviceChange(dev, AudioOutputPrivate::FallbackChange); + return; // found one that works + } + } + // if we get here there is no working output device. Tell the backend. + const AudioOutputDevice none; + callSetOutputDevice(this, none); + handleAutomaticDeviceChange(none, FallbackChange); + } +#endif //QT_NO_PHONON_SETTINGSGROUP +} + +void AudioOutputPrivate::_k_volumeChanged(qreal newVolume) +{ + if (!muted) { + Q_Q(AudioOutput); + emit q->volumeChanged(pow(newVolume, qreal(0.67))); + } +} + +void AudioOutputPrivate::_k_revertFallback() +{ + if (deviceBeforeFallback == -1) { + return; + } + device = AudioOutputDevice::fromIndex(deviceBeforeFallback); + callSetOutputDevice(this, device); + Q_Q(AudioOutput); + emit q->outputDeviceChanged(device); +#ifndef QT_NO_DBUS + emit adaptor->outputDeviceIndexChanged(device.index()); +#endif +} + +void AudioOutputPrivate::_k_audioDeviceFailed() +{ + if (PulseSupport::getInstance()->isActive()) + return; + +#ifndef QT_NO_PHONON_SETTINGSGROUP + + pDebug() << Q_FUNC_INFO; + // outputDeviceIndex identifies a failing device + // fall back in the preference list of output devices + const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); + for (int i = 0; i < deviceList.count(); ++i) { + const int devIndex = deviceList.at(i); + // if it's the same device as the one that failed, ignore it + if (device.index() != devIndex) { + const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex); + if (callSetOutputDevice(this, info)) { + handleAutomaticDeviceChange(info, FallbackChange); + return; // found one that works + } + } + } +#endif //QT_NO_PHONON_SETTINGSGROUP + // if we get here there is no working output device. Tell the backend. + const AudioOutputDevice none; + callSetOutputDevice(this, none); + handleAutomaticDeviceChange(none, FallbackChange); +} + +void AudioOutputPrivate::_k_deviceListChanged() +{ + if (PulseSupport::getInstance()->isActive()) + return; + +#ifndef QT_NO_PHONON_SETTINGSGROUP + pDebug() << Q_FUNC_INFO; + // Check to see if we have an override and do not change to a higher priority device if the overridden device is still present. + if (outputDeviceOverridden && device.property("available").toBool()) { + return; + } + // let's see if there's a usable device higher in the preference list + const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); + DeviceChangeType changeType = HigherPreferenceChange; + for (int i = 0; i < deviceList.count(); ++i) { + const int devIndex = deviceList.at(i); + const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex); + if (!info.property("available").toBool()) { + if (device.index() == devIndex) { + // we've reached the currently used device and it's not available anymore, so we + // fallback to the next available device + changeType = FallbackChange; + } + pDebug() << devIndex << "is not available"; + continue; + } + pDebug() << devIndex << "is available"; + if (device.index() == devIndex) { + // we've reached the currently used device, nothing to change + break; + } + if (callSetOutputDevice(this, info)) { + handleAutomaticDeviceChange(info, changeType); + break; // found one with higher preference that works + } + } +#endif //QT_NO_PHONON_SETTINGSGROUP +} + +void AudioOutputPrivate::_k_deviceChanged(QString inStreamUuid, int deviceIndex) +{ + // Note that this method is only used by PulseAudio at present. + if (inStreamUuid == streamUuid) { + // 1. Check to see if we are overridden. If we are, and devices do not match, + // then try and apply our own device as the output device. + // We only do this the first time + if (outputDeviceOverridden && forceMove) { + forceMove = false; + const AudioOutputDevice ¤tDevice = AudioOutputDevice::fromIndex(deviceIndex); + if (currentDevice != device) { + if (!callSetOutputDevice(this, device)) { + // What to do if we are overridden and cannot change to our preferred device? + } + } + } + // 2. If we are not overridden, then we need to update our perception of what + // device we are using. If the devices do not match, something lower in the + // stack is overriding our preferences (e.g. a per-application stream preference, + // specific application move, priority list changed etc. etc.) + else if (!outputDeviceOverridden) { + const AudioOutputDevice ¤tDevice = AudioOutputDevice::fromIndex(deviceIndex); + if (currentDevice != device) { + // The device is not what we think it is, so lets say what is happening. + handleAutomaticDeviceChange(currentDevice, SoundSystemChange); + } + } + } +} + +static struct +{ + int first; + int second; +} g_lastFallback = { 0, 0 }; + +void AudioOutputPrivate::handleAutomaticDeviceChange(const AudioOutputDevice &device2, DeviceChangeType type) +{ + Q_Q(AudioOutput); + deviceBeforeFallback = device.index(); + device = device2; + emit q->outputDeviceChanged(device2); +#ifndef QT_NO_DBUS + emit adaptor->outputDeviceIndexChanged(device.index()); +#endif + const AudioOutputDevice &device1 = AudioOutputDevice::fromIndex(deviceBeforeFallback); + switch (type) { + case FallbackChange: + if (g_lastFallback.first != device1.index() || g_lastFallback.second != device2.index()) { +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + const QString &text = //device2.isValid() ? + AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>" + "Falling back to <b>%2</b>.</html>").arg(device1.name()).arg(device2.name()) /*: + AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>" + "No other device available.</html>").arg(device1.name())*/; + Platform::notification("AudioDeviceFallback", text); +#endif //QT_NO_PHONON_PLATFORMPLUGIN + g_lastFallback.first = device1.index(); + g_lastFallback.second = device2.index(); + } + break; + case HigherPreferenceChange: + { +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + const QString text = AudioOutput::tr("<html>Switching to the audio playback device <b>%1</b><br/>" + "which just became available and has higher preference.</html>").arg(device2.name()); + Platform::notification("AudioDeviceFallback", text, + QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())), + q, SLOT(_k_revertFallback())); +#endif //QT_NO_PHONON_PLATFORMPLUGIN + g_lastFallback.first = 0; + g_lastFallback.second = 0; + } + break; + case SoundSystemChange: + { +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + if (device1.property("available").toBool()) { + const QString text = AudioOutput::tr("<html>Switching to the audio playback device <b>%1</b><br/>" + "which has higher preference or is specifically configured for this stream.</html>").arg(device2.name()); + Platform::notification("AudioDeviceFallback", text, + QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())), + q, SLOT(_k_revertFallback())); + } else { + const QString &text = + AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>" + "Falling back to <b>%2</b>.</html>").arg(device1.name()).arg(device2.name()); + Platform::notification("AudioDeviceFallback", text); + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + //outputDeviceOverridden = true; + g_lastFallback.first = 0; + g_lastFallback.second = 0; + } + break; + } +} + +AudioOutputPrivate::~AudioOutputPrivate() +{ + PulseSupport::getInstance()->clearStreamCache(streamUuid); +#ifndef QT_NO_DBUS + if (adaptor) { + emit adaptor->outputDestroyed(); + } +#endif +} + +} //namespace Phonon + +QT_END_NAMESPACE + +#include "moc_audiooutput.cpp" + +#undef PHONON_CLASSNAME +#undef PHONON_INTERFACENAME +#undef IFACES2 +#undef IFACES1 +#undef IFACES0 diff --git a/src/3rdparty/phonon/phonon/audiooutput.h b/src/3rdparty/phonon/phonon/audiooutput.h new file mode 100644 index 0000000..513a863 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutput.h @@ -0,0 +1,180 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#ifndef Phonon_AUDIOOUTPUT_H +#define Phonon_AUDIOOUTPUT_H + +#include "phonon_export.h" +#include "abstractaudiooutput.h" +#include "phonondefs.h" +#include "phononnamespace.h" +#include "objectdescription.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QString; + +class AudioOutputAdaptor; +namespace Phonon +{ + class AudioOutputPrivate; + + /** \class AudioOutput audiooutput.h Phonon/AudioOutput + * \short Class for audio output to the soundcard. + * + * Use this class to define the audio output. + * + * \ingroup Frontend + * \author Matthias Kretz <kretz@kde.org> + * \see Phonon::Ui::VolumeSlider + */ + class PHONON_EXPORT AudioOutput : public AbstractAudioOutput + { + friend class FactoryPrivate; + friend class ::AudioOutputAdaptor; + Q_OBJECT + K_DECLARE_PRIVATE(AudioOutput) + /** + * This is the name that appears in Mixer applications that control + * the volume of this output. + * + * \see category + */ + Q_PROPERTY(QString name READ name WRITE setName) + /** + * This is the current loudness of the output (it is using Stevens' law + * to calculate the change in voltage internally). + * + * \see volumeDecibel + */ + Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged) + /** + * This is the current volume of the output in decibel. + * + * 0 dB means no change in volume, -6dB means an attenuation of the + * voltage to 50% and an attenuation of the power to 25%, -inf dB means + * silence. + * + * \see volume + */ + Q_PROPERTY(qreal volumeDecibel READ volumeDecibel WRITE setVolumeDecibel) + /** + * This property holds the (hardware) destination for the output. + * + * The default device is determined by the category and the global + * configuration for that category of outputs. Normally you don't need + * to override this setting - letting the user change the global + * configuration is the right choice. You can still override the + * device though, if you have good reasons to do so. + * + * \see outputDeviceChanged + */ + Q_PROPERTY(AudioOutputDevice outputDevice READ outputDevice WRITE setOutputDevice) + + /** + * This property tells whether the output is muted. + * + * Muting the output has the same effect as calling setVolume(0.0). + */ + Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) + public: + /** + * Creates a new AudioOutput that defines output to a physical + * device. + * + * \param category The category can be used by mixer applications to group volume + * controls of applications into categories. That makes it easier for + * the user to identify the programs. + * The category is also used for the default output device that is + * configured centrally. As an example: often users want to have the + * audio signal of a VoIP application go to their USB headset while + * all other sounds should go to the internal soundcard. + * + * \param parent QObject parent + * + * \see Phonon::categoryToString + * \see outputDevice + */ + explicit AudioOutput(Phonon::Category category, QObject *parent = 0); + explicit AudioOutput(QObject *parent = 0); + + QString name() const; + qreal volume() const; + qreal volumeDecibel() const; + + /** + * Returns the category of this output. + * + * \see AudioOutput(Phonon::Category, QObject *) + */ + Phonon::Category category() const; + AudioOutputDevice outputDevice() const; + bool isMuted() const; + + public Q_SLOTS: + void setName(const QString &newName); + void setVolume(qreal newVolume); + void setVolumeDecibel(qreal newVolumeDecibel); + bool setOutputDevice(const Phonon::AudioOutputDevice &newAudioOutputDevice); + void setMuted(bool mute); + + Q_SIGNALS: + /** + * This signal is emitted whenever the volume has changed. As the + * volume can change without a call to setVolume (calls over dbus) + * this is important + * to keep a widget showing the current volume up to date. + */ + void volumeChanged(qreal newVolume); + + /** + * This signal is emitted when the muted property has changed. As + * this property can change by IPC (DBus) calls a UI element showing + * the muted property should listen to this signal. + */ + void mutedChanged(bool); + + /** + * This signal is emitted when the (hardware) device for the output + * has changed. + * + * The change can happen either through setOutputDevice or if the + * global configuration for the used category has changed. + * + * \see outputDevice + */ + void outputDeviceChanged(const Phonon::AudioOutputDevice &newAudioOutputDevice); + + private: + Q_PRIVATE_SLOT(k_func(), void _k_volumeChanged(qreal)) + Q_PRIVATE_SLOT(k_func(), void _k_revertFallback()) + Q_PRIVATE_SLOT(k_func(), void _k_audioDeviceFailed()) + Q_PRIVATE_SLOT(k_func(), void _k_deviceListChanged()) + Q_PRIVATE_SLOT(k_func(), void _k_deviceChanged(QString streamUuid, int device)) + }; +} //namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_AUDIOOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/audiooutput_p.h b/src/3rdparty/phonon/phonon/audiooutput_p.h new file mode 100644 index 0000000..01dc48f --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutput_p.h @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef AUDIOOUTPUT_P_H +#define AUDIOOUTPUT_P_H + +#include "audiooutput.h" +#include "abstractaudiooutput_p.h" +#include "platform_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +class AudioOutputAdaptor; + +class AudioOutputPrivate : public AbstractAudioOutputPrivate +{ + Q_DECLARE_PUBLIC(AudioOutput) + PHONON_PRIVATECLASS + public: + inline static AudioOutputPrivate *cast(MediaNodePrivate *x) + { + if (x && x->castId == MediaNodePrivate::AudioOutputType) { + return static_cast<AudioOutputPrivate *>(x); + } + return 0; + } + void init(Phonon::Category c); + QString getStreamUuid(); + + + protected: + AudioOutputPrivate(CastId castId = MediaNodePrivate::AudioOutputType) + : AbstractAudioOutputPrivate(castId), + name(Platform::applicationName()), + volume(Platform::loadVolume(name)), +#ifndef QT_NO_DBUS + adaptor(0), +#endif + deviceBeforeFallback(-1), + outputDeviceOverridden(false), + forceMove(false), + muted(false) + { + } + + ~AudioOutputPrivate(); + + enum DeviceChangeType { + FallbackChange, + HigherPreferenceChange, + SoundSystemChange + }; + void handleAutomaticDeviceChange(const AudioOutputDevice &newDev, DeviceChangeType type); + + void _k_volumeChanged(qreal); + void _k_revertFallback(); + void _k_audioDeviceFailed(); + void _k_deviceListChanged(); + void _k_deviceChanged(QString streamUuid, int deviceIndex); + + private: + QString name; + Phonon::AudioOutputDevice device; + qreal volume; + QString streamUuid; +#ifndef QT_NO_DBUS + Phonon::AudioOutputAdaptor *adaptor; +#endif + Category category; + int deviceBeforeFallback; + bool outputDeviceOverridden; + bool forceMove; + bool muted; +}; +} //namespace Phonon + +QT_END_NAMESPACE + +#endif // AUDIOOUTPUT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp new file mode 100644 index 0000000..2c01773 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp @@ -0,0 +1,101 @@ +/* + * This file was generated by dbusidl2cpp version 0.4 + * when processing input file org.kde.Phonon.AudioOutput.xml + * + * dbusidl2cpp is Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. This file has been hand-edited. + */ + +#include "audiooutputadaptor_p.h" +#include "audiooutput.h" +#include <QtCore/QArgument> +#include <QtCore/QByteRef> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include "phononnamespace_p.h" +#include "objectdescription.h" + +#ifndef QT_NO_DBUS + +/* + * Implementation of adaptor class AudioOutputAdaptor + */ + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +AudioOutputAdaptor::AudioOutputAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +AudioOutputAdaptor::~AudioOutputAdaptor() +{ + // destructor +} + +double AudioOutputAdaptor::volume() const +{ + // get the value of property volume + return qvariant_cast<qreal>(parent()->property("volume")); +} + +void AudioOutputAdaptor::setVolume(double value) +{ + // set the value of property volume + parent()->setProperty("volume", QVariant::fromValue(static_cast<qreal>(value))); +} + +bool AudioOutputAdaptor::muted() const +{ + return parent()->property("muted").toBool(); +} + +void AudioOutputAdaptor::setMuted(bool value) +{ + parent()->setProperty("muted", value); +} + +QString AudioOutputAdaptor::category() +{ + // handle method call org.kde.Phonon.AudioOutput.category + return Phonon::categoryToString(static_cast<Phonon::AudioOutput *>(parent())->category()); +} + +QString AudioOutputAdaptor::name() +{ + // handle method call org.kde.Phonon.AudioOutput.name + QString name; + //QMetaObject::invokeMethod(parent(), "name", Q_RETURN_ARG(QString, name)); + + // Alternative: + name = static_cast<Phonon::AudioOutput *>(parent())->name(); + return name; +} + +int AudioOutputAdaptor::outputDeviceIndex() const +{ + return static_cast<Phonon::AudioOutput *>(parent())->outputDevice().index(); +} + +void AudioOutputAdaptor::setOutputDeviceIndex(int newAudioOutputDeviceIndex) +{ + static_cast<Phonon::AudioOutput *>(parent()) + ->setOutputDevice(Phonon::AudioOutputDevice::fromIndex(newAudioOutputDeviceIndex)); +} + +} // namespace Phonon + +QT_END_NAMESPACE + +#include "moc_audiooutputadaptor_p.cpp" + +#endif diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h new file mode 100644 index 0000000..7178e9b --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h @@ -0,0 +1,109 @@ +/* + * This file was generated by dbusidl2cpp version 0.4 + * when processing input file org.kde.Phonon.AudioOutput.xml + * + * dbusidl2cpp is Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. This file has been hand-edited. + */ + +#ifndef AUDIOOUTPUTADAPTOR_P_H +#define AUDIOOUTPUTADAPTOR_P_H + +#include <QtCore/QObject> + +#ifndef QT_NO_DBUS +#include <QtDBus/QtDBus> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QByteArray; +template<class T> class QList; +template<class Key, class Value> class QMap; +class QString; +class QStringList; +class QVariant; + +namespace Phonon +{ + class AudioOutputPrivate; + class AudioOutput; + +/* + * Adaptor class for interface org.kde.Phonon.AudioOutput + */ +class AudioOutputAdaptor: public QDBusAbstractAdaptor +{ + friend class Phonon::AudioOutputPrivate; + friend class Phonon::AudioOutput; + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.Phonon.AudioOutput") + Q_CLASSINFO("D-Bus Introspection", "" +" <interface name=\"org.kde.Phonon.AudioOutput\" >\n" +" <property access=\"readwrite\" type=\"d\" name=\"volume\" />\n" +" <property access=\"readwrite\" type=\"b\" name=\"muted\" />\n" +" <property access=\"readwrite\" type=\"i\" name=\"outputDeviceIndex\" />\n" +" <signal name=\"volumeChanged\" >\n" +" <arg direction=\"out\" type=\"d\" />\n" +" </signal>\n" +" <signal name=\"mutedChanged\" >\n" +" <arg direction=\"out\" type=\"b\" />\n" +" </signal>\n" +" <signal name=\"outputDeviceIndexChanged\" >\n" +" <arg direction=\"out\" type=\"i\" />\n" +" </signal>\n" +" <signal name=\"nameChanged\" >\n" +" <arg direction=\"out\" type=\"s\" name=\"newName\" />\n" +" </signal>\n" +" <signal name=\"newOutputAvailable\" >\n" +" <arg direction=\"out\" type=\"s\" name=\"service\" />\n" +" <arg direction=\"out\" type=\"s\" name=\"path\" />\n" +" </signal>\n" +" <signal name=\"outputDestroyed\" >\n" +" </signal>\n" +" <method name=\"category\" >\n" +" <arg direction=\"out\" type=\"s\" />\n" +" </method>\n" +" <method name=\"name\" >\n" +" <arg direction=\"out\" type=\"s\" />\n" +" </method>\n" +" </interface>\n" + "") +public: + AudioOutputAdaptor(QObject *parent); + virtual ~AudioOutputAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool muted READ muted WRITE setMuted) + bool muted() const; + void setMuted(bool value); + + Q_PROPERTY(int outputDeviceIndex READ outputDeviceIndex WRITE setOutputDeviceIndex) + int outputDeviceIndex() const; + void setOutputDeviceIndex(int value); + + Q_PROPERTY(double volume READ volume WRITE setVolume) + double volume() const; + void setVolume(double value); + +public Q_SLOTS: // METHODS + QString category(); + QString name(); +Q_SIGNALS: // SIGNALS + void mutedChanged(bool in0); + void nameChanged(const QString &newName); + void newOutputAvailable(const QString &service, const QString &path); + void outputDestroyed(); + void outputDeviceIndexChanged(int in0); + void volumeChanged(qreal in0); +}; + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QT_NO_DBUS + +#endif // AUDIOOUTPUTADAPTOR_P_H diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.cpp b/src/3rdparty/phonon/phonon/audiooutputinterface.cpp new file mode 100644 index 0000000..1770f4c --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutputinterface.cpp @@ -0,0 +1,40 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "audiooutputinterface.h" +#include <QtCore/QList> +#include <QtCore/QStringList> +#include <QtCore/QPair> +#include "platform_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +QList<QPair<QByteArray, QString> > AudioOutputInterface42::deviceAccessListFor(const Phonon::AudioOutputDevice &deviceDesc) const +{ + return Platform::deviceAccessListFor(deviceDesc); +} + +} // namespace Phonon + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.h b/src/3rdparty/phonon/phonon/audiooutputinterface.h new file mode 100644 index 0000000..cce12b2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiooutputinterface.h @@ -0,0 +1,151 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_AUDIOOUTPUTINTERFACE_H +#define PHONON_AUDIOOUTPUTINTERFACE_H + +#include "phononnamespace.h" +#include "objectdescription.h" +#include "phonondefs.h" +#include <QtCore/QtGlobal> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +/** \class AudioOutputInterface audiooutputinterface.h Phonon/AudioOutputInterface + * \short Interface for AudioOutput objects + * + * The implementation can make use of the signals + * \code + void volumeChanged(qreal newVolume); + void audioDeviceFailed(); + * \endcode + * to notify the frontend whenever the volume has changed or when an audioDeviceFailed (e.g. USB + * unplug or sound server failure). + * + * \author Matthias Kretz <kretz@kde.org> + */ +class AudioOutputInterface40 +{ + public: + virtual ~AudioOutputInterface40() {} + + /** + * Returns the current software volume. + * + * A value of 0.0 means muted, 1.0 means unchanged, 2.0 means double voltage (i.e. all + * samples are multiplied by 2). + */ + virtual qreal volume() const = 0; + /** + * Sets the new current software volume. + * + * A value of 0.0 means muted, 1.0 means unchanged, 2.0 means double voltage (i.e. all + * samples are multiplied by 2). + * + * Every time the volume in the backend changes it should emit volumeChanged(qreal), also + * inside this function. + */ + virtual void setVolume(qreal) = 0; + + /** + * Returns the index of the device that is used. The index is the number returned from + * BackendInterface::objectDescriptionIndexes(AudioOutputDeviceType). + */ + virtual int outputDevice() const = 0; + /** + * \deprecated + * + * Requests to change the current output device to the one identified by the passed index. + * + * The index is the number returned from + * BackendInterface::objectDescriptionIndexes(AudioOutputDeviceType). + * + * \returns \c true if the requested device works and is used after this call. + * \returns \c false if something failed and the device is not used after this call. + */ + virtual bool setOutputDevice(int) = 0; +}; + +class AudioOutputInterface42 : public AudioOutputInterface40 +{ + public: + /** + * Requests to change the current output device. + * + * \returns \c true if the requested device works and is used after this call. + * \returns \c false if something failed and the device is not used after this call. + */ + virtual bool setOutputDevice(const Phonon::AudioOutputDevice &) = 0; + + using AudioOutputInterface40::setOutputDevice; + + /** + * Helper function for backends to get a list of (driver, handle) pairs for + * AudioOutputDevice objects that are listed by the platform plugin. + * + * Example: + * \code + typedef QPair<QByteArray, QString> PhononDeviceAccess; + const QList<PhononDeviceAccess> &deviceAccessList = deviceAccessListFor(deviceDesc); + foreach (const PhononDeviceAccess &access, deviceAccessList) { + const QByteArray &driver = access.first; + const QString &handle = access.second; + if (openDevice(driver, handle)) { + // we found the first pair in the list that works. done. + return; + } + // continue trying the other (driver, handle) pairs + } + // none of the (driver, handle) pairs worked, that means the whole AudioOutputDevice is + // inaccessible and the frontend needs to know (either by emitting audioDeviceFailed or + // returning false when called from setOutputDevice) + * \endcode + * + * At the time of this writing the following driver strings are known to be in use: + * \li \c alsa: The handle is the string to pass to snd_pcm_open (e.g. "dmix:CARD=0,DEV=1") + * \li \c oss: The handle is the device file (e.g. "/dev/dsp") + * \li \c pulseaudio: The handle contains the server string and the sink/source name + * separated by a newline character. + * (e.g. unix:/tmp/pulse-mkretz/native\nalsa_output.pci_8086_293e_sound_card_0_alsa_playback_0) + */ + PHONON_EXPORT QList<QPair<QByteArray, QString> > deviceAccessListFor(const Phonon::AudioOutputDevice &) const; +}; + +} // namespace Phonon + +#ifdef PHONON_BACKEND_VERSION_4_2 +namespace Phonon { typedef AudioOutputInterface42 AudioOutputInterface; } +Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface40, "AudioOutputInterface2.phonon.kde.org") +Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface, "3AudioOutputInterface.phonon.kde.org") +#else +namespace Phonon { typedef AudioOutputInterface40 AudioOutputInterface; } +Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface, "AudioOutputInterface2.phonon.kde.org") +Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface42, "3AudioOutputInterface.phonon.kde.org") +#endif + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_AUDIOOUTPUTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/backend.dox b/src/3rdparty/phonon/phonon/backend.dox new file mode 100644 index 0000000..8a9c5b2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/backend.dox @@ -0,0 +1,107 @@ +/** +\page phonon_Backend The Backend Class +\ingroup Backend + +\section phonon_Backend_requiredfunctions Required Functions +\li bool \ref phonon_Backend_supportsOSD "supportsOSD()" +\li bool \ref phonon_Backend_supportsFourcc "supportsFourcc( quint32 )" +\li bool \ref phonon_Backend_supportsSubtitles "supportsSubtitles()" +\li bool \ref phonon_Backend_supportsVideo "supportsVideo()" +\li QStringList \ref phonon_Backend_availableMimeTypes "availableMimeTypes()" + +\section Member Function Documentation + +\subsection phonon_Backend_supportsFourcc bool supportsFourcc( quint32 fourcc ) +Tells whether the FOURCC (four character code) is supported for +the \ref phonon_VideoDataOutput "VideoDataOutput" interface. If you return \c true, you have to be +able to return VideoFrame objects accordingly from +\ref phonon_VideoDataOutput "VideoDataOutput". +\param fourcc A four character code defining a video frame format. +\returns \c true if your \ref phonon_VideoDataOutput "VideoDataOutput" can +output video frames in the requested format. +\returns \c false if the video frames can not be converted into the requested +format. + +\subsection phonon_Backend_availableMimeTypes QStringList availableMimeTypes() +Lists the MIME types the backend can read and decode. + +\subsection phonon_Backend_xIndexes QSet<int> <device/codec/effect/...>Indexes() + Returns a set of indexes that identify the devices/codecs/effects/... the + backend supports. This list needs to be compiled from looking at + available hardware and virtual devices/plugins/... . The implementation + should use cached information, but you need to invalidate the cache + whenever the hardware configuration changes or new virtual devices come + available/new plugins are installed/... . + + \return The indexes of the available devices/codecs/effects/... + + \see \ref phonon_Backend_xName + \see \ref phonon_Backend_xDescription + +\subsection phonon_Backend_xName QString <device/codec/effect/...>Name( int index ) + Returns the name of the given device/codec/effect/... + + \param index The index of one device/codec/effect/... this is one index + out of \ref phonon_Backend_xIndexes + + \returns A translated user visible string to name the device. + + \see \ref phonon_Backend_xIndexes + \see \ref phonon_Backend_xDescription +\subsection phonon_Backend_xDescription QString <device/codec/effect/...>Description( int index ) + Returns the description of the given device/codec/effect/... + + \param index The index of one device/codec/effect/... this is one index + out of \ref phonon_Backend_xIndexes + + \returns A translated user visible string to describe the device. + + \see \ref phonon_Backend_xIndexes + \see \ref phonon_Backend_xName + +\subsection phonon_Backend_audioCaptureDeviceVideoIndex qint32 audioCaptureDeviceVideoIndex( int index ) + \param index The index of the device. This is one of the indexes the backend + returned via \ref phonon_Backend_xIndexes + \returns An index of a video capture device that is associated with the given + audio capture device. For example a webcam might have both a video and an audio + capture device, and in order give the user a hint that the audio and video + capture devices belong together this index is used. + \returns If there is no associated video capture device return -1. + +\subsection phonon_Backend_videoCaptureDeviceAudioIndex qint32 videoCaptureDeviceAudioIndex( int index ) + \param index The index of the device. This is one of the indexes the backend + returned via \ref phonon_Backend_xIndexes + \returns An index of a audio capture device that is associated with the given + video capture device. For example a webcam might have both a audio and an video + capture device, and in order give the user a hint that the video and audio + capture devices belong together this index is used. + \returns If there is no associated audio capture device return -1. + +\page phonon_AudioDataOutput The AudioDataOutput Class +\ingroup Backend + +\page phonon_AudioOutput The AudioOutput Class +\ingroup Backend + +\page phonon_VideoDataOutput The VideoDataOutput Class +\ingroup Backend + +\page phonon_VideoWidget The VideoWidget Class +\ingroup Backend + +\page phonon_Effect The Effect Class +\ingroup Backend + +\page phonon_BrightnessControl The BrightnessControl Class +\ingroup Backend + +\page phonon_VideoEffect The VideoEffect Class +\ingroup Backend + +\page phonon_Visualization The Visualization Class +\ingroup Backend + +\page phonon_VolumeFaderEffect The VolumeFaderEffect Class +\ingroup Backend + +*/ diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp new file mode 100644 index 0000000..8dad589 --- /dev/null +++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "backendcapabilities.h" +#include "backendcapabilities_p.h" + +#include "phonondefs_p.h" +#include "backendinterface.h" +#include "factory_p.h" +#include "globalconfig.h" +#include "globalstatic_p.h" +#include "objectdescription.h" + +#include <QtCore/QList> +#include <QtCore/QSet> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE + +PHONON_GLOBAL_STATIC(Phonon::BackendCapabilitiesPrivate, globalBCPrivate) + +namespace Phonon +{ + +BackendCapabilities::Notifier *BackendCapabilities::notifier() +{ + return globalBCPrivate; +} + +QStringList BackendCapabilities::availableMimeTypes() +{ + if (BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend())) + return backendIface->availableMimeTypes(); + else + return QStringList(); +} + +bool BackendCapabilities::isMimeTypeAvailable(const QString &mimeType) +{ + QObject *m_backendObject = Factory::backend(false); + if (!m_backendObject) { + if (!Factory::isMimeTypeAvailable(mimeType)) { + return false; + } + // without loading the backend we found out that the MIME type might be supported, now we + // want to know for certain. For that we need to load the backend. + m_backendObject = Factory::backend(true); + } + if (!m_backendObject) { + // no backend == no MIME type supported at all + return false; + } + return availableMimeTypes().contains(mimeType); +} + +QList<AudioOutputDevice> BackendCapabilities::availableAudioOutputDevices() +{ + QList<AudioOutputDevice> ret; +#ifndef QT_NO_PHONON_SETTINGSGROUP + const QList<int> deviceIndexes = GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory); + for (int i = 0; i < deviceIndexes.count(); ++i) { + ret.append(AudioOutputDevice::fromIndex(deviceIndexes.at(i))); + } +#endif //QT_NO_PHONON_SETTINGSGROUP + return ret; +} + + +#ifndef QT_NO_PHONON_AUDIOCAPTURE +QList<AudioCaptureDevice> BackendCapabilities::availableAudioCaptureDevices() +{ + QList<AudioCaptureDevice> ret; + const QList<int> deviceIndexes = GlobalConfig().audioCaptureDeviceListFor(Phonon::NoCategory); + for (int i = 0; i < deviceIndexes.count(); ++i) { + ret.append(AudioCaptureDevice::fromIndex(deviceIndexes.at(i))); + } + return ret; +} +#endif //QT_NO_PHONON_AUDIOCAPTURE + +#ifndef QT_NO_PHONON_EFFECT +QList<EffectDescription> BackendCapabilities::availableAudioEffects() +{ + BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend()); + QList<EffectDescription> ret; + if (backendIface) { + const QList<int> deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::EffectType); + for (int i = 0; i < deviceIndexes.count(); ++i) { + ret.append(EffectDescription::fromIndex(deviceIndexes.at(i))); + } + } + return ret; +} +#endif //QT_NO_PHONON_EFFECT + +} // namespace Phonon + +QT_END_NAMESPACE + +#include "moc_backendcapabilities.cpp" + +// vim: sw=4 ts=4 + + diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.h b/src/3rdparty/phonon/phonon/backendcapabilities.h new file mode 100644 index 0000000..643c8ef --- /dev/null +++ b/src/3rdparty/phonon/phonon/backendcapabilities.h @@ -0,0 +1,212 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef Phonon_BACKENDCAPABILITIES_H +#define Phonon_BACKENDCAPABILITIES_H + +#include "phonon_export.h" +#include "objectdescription.h" + +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifdef __QT_SYNCQT__ +// Tell syncqt that the BackendCapabilities namespace should be treated like a class +#pragma qt_class(Phonon::BackendCapabilities) +#pragma qt_sync_stop_processing +#endif + +template<class T> class QList; +class QStringList; + +namespace Phonon +{ + +/** + * Collection of functions describing the capabilities of the Backend. + * + * \ingroup BackendInformation + * \author Matthias Kretz <kretz@kde.org> + */ +namespace BackendCapabilities +{ + /** \class Notifier backendcapabilities.h Phonon/BackendCapabilities + * Notifications about backend capabilities. + * + * \ingroup BackendInformation + */ + class Notifier : public QObject + { + Q_OBJECT + Q_SIGNALS: + /** + * This signal is emitted if the capabilities have changed. This can + * happen if the user has requested a backend change. + */ + void capabilitiesChanged(); + + /** + * This signal is emitted when audio output devices were plugged or + * unplugged. + * + * Check BackendCapabilities::availableAudioOutputDevices to get the + * current list of available devices. + */ + void availableAudioOutputDevicesChanged(); + + /** + * This signal is emitted when audio capture devices were plugged or + * unplugged. + * + * Check BackendCapabilities::availableAudioCaptureDevices to get the + * current list of available devices. + */ +#ifndef QT_NO_PHONON_AUDIOCAPTURE + void availableAudioCaptureDevicesChanged(); +#endif //QT_NO_PHONON_AUDIOCAPTURE + }; + + /** + * Use this function to get a QObject pointer to connect to one of the Notifier signals. + * + * \return a pointer to a QObject. + * + * To connect to the signal do the following: + * \code + * QObject::connect(BackendCapabilities::notifier(), SIGNAL(capabilitiesChanged()), ... + * \endcode + * + * \see Notifier::capabilitiesChanged() + * \see Notifier::availableAudioOutputDevicesChanged() + * \see Notifier::availableAudioCaptureDevicesChanged() + */ + PHONON_EXPORT Notifier *notifier(); + + /** + * Returns a list of mime types that the Backend can decode. + * + * \see isMimeTypeAvailable() + */ + PHONON_EXPORT QStringList availableMimeTypes(); + + /** + * Often all you want to know is whether one given MIME type can be + * decoded by the backend. Use this method in favor of availableMimeTypes() + * as it can give you a negative answer without having a backend loaded. + * + * \see availableMimeTypes(); + */ + PHONON_EXPORT bool isMimeTypeAvailable(const QString &mimeType); + + /** + * Returns the audio output devices the backend supports. + * + * \return A list of AudioOutputDevice objects that give a name and + * description for every supported audio output device. + */ + PHONON_EXPORT QList<AudioOutputDevice> availableAudioOutputDevices(); + + /** + * Returns the audio capture devices the backend supports. + * + * \return A list of AudioCaptureDevice objects that give a name and + * description for every supported audio capture device. + */ +#ifndef QT_NO_PHONON_AUDIOCAPTURE + PHONON_EXPORT QList<AudioCaptureDevice> availableAudioCaptureDevices(); +#endif //QT_NO_PHONON_AUDIOCAPTURE + + /** + * Returns the video output devices the backend supports. + * + * \return A list of VideoOutputDevice objects that give a name and + * description for every supported video output device. + */ +// PHONON_EXPORT QList<VideoOutputDevice> availableVideoOutputDevices(); + + /** + * Returns the video capture devices the backend supports. + * + * \return A list of VideoCaptureDevice objects that give a name and + * description for every supported video capture device. + */ +// PHONON_EXPORT QList<VideoCaptureDevice> availableVideoCaptureDevices(); + + /** + * Returns the visualization effects the backend supports. + * + * \return A list of VisualizationEffect objects that give a name and + * description for every supported visualization effect. + */ +// PHONON_EXPORT QList<VisualizationDescription> availableVisualizations(); + + /** + * Returns descriptions for the audio effects the backend supports. + * + * \return A list of AudioEffectDescription objects that give a name and + * description for every supported audio effect. + */ +#ifndef QT_NO_PHONON_EFFECT + PHONON_EXPORT QList<EffectDescription> availableAudioEffects(); +#endif //QT_NO_PHONON_EFFECT + +//X /** +//X * Returns descriptions for the video effects the backend supports. +//X * +//X * \return A list of VideoEffectDescription objects that give a name and +//X * description for every supported video effect. +//X */ +//X PHONON_EXPORT QList<EffectDescription> availableVideoEffects(); + + /** + * Returns descriptions for the audio codecs the backend supports. + * + * \return A list of AudioCodec objects that give a name and + * description for every supported audio codec. + */ +// PHONON_EXPORT QList<AudioCodecDescription> availableAudioCodecs(); + + /** + * Returns descriptions for the video codecs the backend supports. + * + * \return A list of VideoCodec objects that give a name and + * description for every supported video codec. + */ +// PHONON_EXPORT QList<VideoCodecDescription> availableVideoCodecs(); + + /** + * Returns descriptions for the container formats the backend supports. + * + * \return A list of ContainerFormat objects that give a name and + * description for every supported container format. + */ +// PHONON_EXPORT QList<ContainerFormatDescription> availableContainerFormats(); +} // namespace BackendCapabilities +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // Phonon_BACKENDCAPABILITIES_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/backendcapabilities_p.h b/src/3rdparty/phonon/phonon/backendcapabilities_p.h new file mode 100644 index 0000000..5ef18a4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/backendcapabilities_p.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_BACKENDCAPABILITIES_P_H +#define PHONON_BACKENDCAPABILITIES_P_H + +#include "backendcapabilities.h" +#include <QtCore/QObject> +#include "factory_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +class BackendCapabilitiesPrivate : public BackendCapabilities::Notifier +{ + public: + BackendCapabilitiesPrivate() + { + connect(Factory::sender(), SIGNAL(backendChanged()), SIGNAL(capabilitiesChanged())); + connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SIGNAL(availableAudioOutputDevicesChanged())); + connect(Factory::sender(), SIGNAL(availableAudioCaptureDevicesChanged()), SIGNAL(availableAudioCaptureDevicesChanged())); + } +}; + +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // PHONON_BACKENDCAPABILITIES_P_H +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/backendinterface.h b/src/3rdparty/phonon/phonon/backendinterface.h new file mode 100644 index 0000000..5deee75 --- /dev/null +++ b/src/3rdparty/phonon/phonon/backendinterface.h @@ -0,0 +1,287 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_BACKENDINTERFACE_H +#define PHONON_BACKENDINTERFACE_H + +#include "phonon_export.h" +#include "objectdescription.h" + +#include <QtCore/QtGlobal> +#include <QtCore/QSet> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QVariant; + +namespace Phonon +{ + +/** \class BackendInterface backendinterface.h Phonon/BackendInterface + * \short Main Backend class interface + * + * This interface defines the main factory of the backend. The createObject function creates all the + * objects needed by the frontend. + * + * The objectDescriptionIndexes and objectDescriptionProperties functions return information about + * available devices, effects and codecs. + * + * An implementation could look like this: + * \code + * QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args) + * { + * switch (c) { + * case MediaObjectClass: + * return new MediaObject(parent); + * case VolumeFaderEffectClass: + * return new VolumeFaderEffect(parent); + * case AudioOutputClass: + * return new AudioOutput(parent); + * case AudioDataOutputClass: + * return new AudioDataOutput(parent); + * case VisualizationClass: + * return new Visualization(parent); + * case VideoDataOutputClass: + * return new VideoDataOutput(parent); + * case EffectClass: + * return new Effect(args[0].toInt(), parent); + * case VideoWidgetClass: + * return new VideoWidget(qobject_cast<QWidget *>(parent)); + * } + * return 0; + * } + * + * QSet<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const + * { + * QSet<int> set; + * switch(type) + * { + * case Phonon::AudioOutputDeviceType: + * // use AudioDeviceEnumerator to list ALSA and OSS devices + * set << 10000 << 10001; + * break; + * case Phonon::AudioCaptureDeviceType: + * set << 20000 << 20001; + * break; + * case Phonon::VideoOutputDeviceType: + * break; + * case Phonon::VideoCaptureDeviceType: + * set << 30000 << 30001; + * break; + * case Phonon::VisualizationType: + * case Phonon::AudioCodecType: + * case Phonon::VideoCodecType: + * case Phonon::ContainerFormatType: + * break; + * case Phonon::EffectType: + * set << 0x7F000001; + * break; + * } + * return set; + * } + * + * QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const + * { + * QHash<QByteArray, QVariant> ret; + * switch (type) { + * case Phonon::AudioOutputDeviceType: + * switch (index) { + * case 10000: + * ret.insert("name", QLatin1String("internal Soundcard")); + * break; + * case 10001: + * ret.insert("name", QLatin1String("USB Headset")); + * ret.insert("icon", KIcon("usb-headset")); + * ret.insert("available", false); + * break; + * } + * break; + * case Phonon::AudioCaptureDeviceType: + * switch (index) { + * case 20000: + * ret.insert("name", QLatin1String("Soundcard")); + * ret.insert("description", QLatin1String("first description")); + * break; + * case 20001: + * ret.insert("name", QLatin1String("DV")); + * ret.insert("description", QLatin1String("second description")); + * break; + * } + * break; + * case Phonon::VideoOutputDeviceType: + * break; + * case Phonon::VideoCaptureDeviceType: + * switch (index) { + * case 30000: + * ret.insert("name", QLatin1String("USB Webcam")); + * ret.insert("description", QLatin1String("first description")); + * break; + * case 30001: + * ret.insert("name", QLatin1String("DV")); + * ret.insert("description", QLatin1String("second description")); + * break; + * } + * break; + * case Phonon::VisualizationType: + * break; + * case Phonon::AudioCodecType: + * break; + * case Phonon::VideoCodecType: + * break; + * case Phonon::ContainerFormatType: + * break; + * case Phonon::EffectType: + * switch (index) { + * case 0x7F000001: + * ret.insert("name", QLatin1String("Delay")); + * ret.insert("description", QLatin1String("Simple delay effect with time, feedback and level controls.")); + * break; + * } + * break; + * } + * return ret; + * } + * \endcode + * + * \author Matthias Kretz <kretz@kde.org> + */ +class BackendInterface +{ + public: + /** + * \internal + * + * Silence gcc's warning. + */ + virtual ~BackendInterface() {} + + /** + * Classes that the createObject function has to handle. + */ + enum Class { + /** + * Request to return a %MediaObject object. + */ + MediaObjectClass, + /** + * Request to return a %VolumeFaderEffect object. + */ + VolumeFaderEffectClass, + /** + * Request to return a %AudioOutput object. + */ + AudioOutputClass, + /** + * Request to return a %AudioDataOutput object. + */ + AudioDataOutputClass, + /** + * Request to return a %Visualization object. + */ + VisualizationClass, + /** + * Request to return a %VideoDataOutput object. + */ + VideoDataOutputClass, + /** + * Request to return a %Effect object. + * + * Takes an additional int that specifies the effect Id. + */ + EffectClass, + /** + * Request to return a %VideoWidget object. + */ + VideoWidgetClass + }; + + /** + * Returns a new instance of the requested class. + * + * \param c The requested class. + * \param parent The parent object. + * \param args Additional arguments (documented in \ref Class). + */ + virtual QObject *createObject(Class c, QObject *parent, const QList<QVariant> &args = QList<QVariant>()) = 0; + + /** + * Returns the unique identifiers for the devices/effects/codecs of the given \p type. + * + * \param type see \ref ObjectDescriptionType + */ + virtual QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const = 0; + + /** + * Given a unique identifier that was returned from objectDescriptionIndexes this function + * returns a hash mapping property names to values. + * + * The property "name" must always be present. All other properties are optional. + * + * List of possible properties: + * \li \c \b name: The name of the device/effect/codec/... + * \li \c \b description: A text explaining what this device/effect/codec/... is/can do + * \li \c \b icon: An icon name (using the freedesktop naming scheme) or a QIcon for this + * device/effect/codec/... + * \li \c \b available: A bool telling whether the device is present or unplugged. + * + * \param type see \ref ObjectDescriptionType + * \param index The unique identifier that is returned from objectDescriptionIndexes + */ + virtual QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const = 0; + + /** + * When this function is called the nodes given in the parameter list should not lose any + * signal data when connections are changed. + */ + virtual bool startConnectionChange(QSet<QObject *>) = 0; + + /** + * Defines a signal connection between the two given nodes. + */ + virtual bool connectNodes(QObject *, QObject *) = 0; + + /** + * Cuts a signal connection between the two given nodes. + */ + virtual bool disconnectNodes(QObject *, QObject *) = 0; + + /** + * When this function is called the nodes given in the parameter list may lose + * signal data when a port is not connected. + */ + virtual bool endConnectionChange(QSet<QObject *>) = 0; + + /** + * gets all available mime types + */ + virtual QStringList availableMimeTypes() const = 0; + +}; +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::BackendInterface, "BackendInterface3.phonon.kde.org") + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_BACKENDINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/effect.cpp b/src/3rdparty/phonon/phonon/effect.cpp new file mode 100644 index 0000000..dfcb290 --- /dev/null +++ b/src/3rdparty/phonon/phonon/effect.cpp @@ -0,0 +1,138 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "effect.h" +#include "effect_p.h" +#include "effectparameter.h" +#include "effectinterface.h" +#include "factory_p.h" + +#define PHONON_INTERFACENAME EffectInterface + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +namespace Phonon +{ +Effect::~Effect() +{ +} + +Effect::Effect(const EffectDescription &description, QObject *parent) + : QObject(parent), MediaNode(*new EffectPrivate) +{ + K_D(Effect); + d->description = description; + d->createBackendObject(); +} + +Effect::Effect(EffectPrivate &dd, QObject *parent) + : QObject(parent), MediaNode(dd) +{ +} + +void EffectPrivate::createBackendObject() +{ + if (m_backendObject) + return; + Q_Q(Effect); + m_backendObject = Factory::createEffect(description.index(), q); + if (m_backendObject) { + setupBackendObject(); + } +} + +//X Effect::Type Effect::type() const +//X { +//X K_D(const Effect); +//X return d->type; +//X } +//X +EffectDescription Effect::description() const +{ + K_D(const Effect); + return d->description; +} + +QList<EffectParameter> Effect::parameters() const +{ + K_D(const Effect); + // there should be an iface object, but better be safe for those backend + // switching corner-cases: when the backend switches the new backend might + // not support this effect -> no iface object + if (d->m_backendObject) { + return INTERFACE_CALL(parameters()); + } + return QList<EffectParameter>(); +} + +QVariant Effect::parameterValue(const EffectParameter ¶m) const +{ + K_D(const Effect); + if (!d->m_backendObject) { + return d->parameterValues[param]; + } + return INTERFACE_CALL(parameterValue(param)); +} + +void Effect::setParameterValue(const EffectParameter ¶m, const QVariant &newValue) +{ + K_D(Effect); + d->parameterValues[param] = newValue; + if (d->backendObject()) { + INTERFACE_CALL(setParameterValue(param, newValue)); + } +} + +bool EffectPrivate::aboutToDeleteBackendObject() +{ + if (m_backendObject) { + const QList<EffectParameter> parameters = pINTERFACE_CALL(parameters()); + for (int i = 0; i < parameters.count(); ++i) { + const EffectParameter &p = parameters.at(i); + parameterValues[p] = pINTERFACE_CALL(parameterValue(p)); + } + } + return true; +} + +void EffectPrivate::setupBackendObject() +{ + Q_ASSERT(m_backendObject); + + // set up attributes + const QList<EffectParameter> parameters = pINTERFACE_CALL(parameters()); + for (int i = 0; i < parameters.count(); ++i) { + const EffectParameter &p = parameters.at(i); + pINTERFACE_CALL(setParameterValue(p, parameterValues[p])); + } +} + +} //namespace Phonon + +#endif //QT_NO_PHONON_EFFECT + +QT_END_NAMESPACE + +#include "moc_effect.cpp" + +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/effect.h b/src/3rdparty/phonon/phonon/effect.h new file mode 100644 index 0000000..e403482 --- /dev/null +++ b/src/3rdparty/phonon/phonon/effect.h @@ -0,0 +1,119 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#ifndef PHONON_EFFECT_H +#define PHONON_EFFECT_H + +#include "phonondefs.h" +#include <QtCore/QObject> +#include "objectdescription.h" +#include "medianode.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +class QString; +template<class T> class QList; + +namespace Phonon +{ + class EffectParameter; + class EffectPrivate; + + /** \class Effect effect.h Phonon/Effect + * \short Effects that can be inserted into a Path. + * An effect is a special object which can perform + * transformations on the specified path. Examples may include simple + * modifiers such as fading or pitch shifting, or more complex mathematical + * transformations. + * + * In order to use an effect, insert it into the path as follows: + * \code + * Path path = Phonon::createPath(...); + * Effect *effect = new Effect(this); + * path.insertEffect(effect); + * \endcode + * + * The effect will immediately begin applying it's transformations on + * the path. To stop it, remove the Effect from the path. + * + * \ingroup PhononEffects + * \author Matthias Kretz <kretz@kde.org> + */ + class PHONON_EXPORT Effect : public QObject, public MediaNode + { + Q_OBJECT + K_DECLARE_PRIVATE(Effect) + + public: + ~Effect(); + +//X enum Type { +//X AudioEffect, +//X VideoEffect +//X }; + + /** + * QObject constructor. + * + * \param description An EffectDescription object to determine the + * type of effect. See BackendCapabilities::availableAudioEffects(). + * \param parent QObject parent + */ + explicit Effect(const EffectDescription &description, QObject *parent = 0); + +//X Type type() const; + + /** + * Returns the description of this effect. This is the same type as was + * passed to the constructor. + */ + EffectDescription description() const; + + /** + * Returns a list of parameters that this effect provides to control + * its behaviour. + * + * \see EffectParameter + * \see EffectWidget + */ + QList<EffectParameter> parameters() const; + + QVariant parameterValue(const EffectParameter&) const; + void setParameterValue(const EffectParameter&, const QVariant &value); + + protected: + Effect(EffectPrivate &dd, QObject *parent); + }; +} //namespace Phonon + +#endif // QT_NO_EFFECT + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // PHONON_EFFECT_H + diff --git a/src/3rdparty/phonon/phonon/effect_p.h b/src/3rdparty/phonon/phonon/effect_p.h new file mode 100644 index 0000000..6cc42d9 --- /dev/null +++ b/src/3rdparty/phonon/phonon/effect_p.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef EFFECT_P_H +#define EFFECT_P_H + +#include "effect.h" +#include "effectparameter.h" +#include "medianode_p.h" +#include <QtCore/QHash> +#include <QtCore/QVariant> +#include "phonondefs_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +namespace Phonon +{ +class EffectPrivate : public MediaNodePrivate +{ + Q_DECLARE_PUBLIC(Effect) + PHONON_PRIVATECLASS + public: + virtual QObject *qObject() { return q_func(); } + protected: + EffectPrivate() + { + } + +//X Effect::Type type; + EffectDescription description; + QHash<EffectParameter, QVariant> parameterValues; +}; +} //namespace Phonon + +QT_END_NAMESPACE + +#endif //QT_NO_PHONON_EFFECT + +#endif // EFFECT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/effectinterface.h b/src/3rdparty/phonon/phonon/effectinterface.h new file mode 100644 index 0000000..59c69d9 --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectinterface.h @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_EFFECTINTERFACE_H +#define PHONON_EFFECTINTERFACE_H + +#include "phononnamespace.h" +#include <QtCore/QVariant> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +namespace Phonon +{ + class EffectParameter; + /** \class EffectInterface effectinterface.h Phonon/EffectInterface + * \short Interface for Effect objects + * + * \author Matthias Kretz <kretz@kde.org> + */ + class EffectInterface + { + public: + virtual ~EffectInterface() {} + /** + * Returns the EffectParameter objects to describe the parameters of this effect. + */ + virtual QList<EffectParameter> parameters() const = 0; + /** + * Returns the value for the selected parameter. + */ + virtual QVariant parameterValue(const EffectParameter &) const = 0; + /** + * Sets the value for the selected parameter. + */ + virtual void setParameterValue(const EffectParameter &, const QVariant &newValue) = 0; + }; +} //namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::EffectInterface, "EffectInterface0.phonon.kde.org") + +#endif //QT_NO_PHONON_EFFECT + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_EFFECTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/effectparameter.cpp b/src/3rdparty/phonon/phonon/effectparameter.cpp new file mode 100644 index 0000000..0447f5b --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectparameter.cpp @@ -0,0 +1,142 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "effectparameter.h" +#include "effectparameter_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +namespace Phonon +{ + +uint qHash(const Phonon::EffectParameter ¶m) +{ + return param.id(); +} + +EffectParameter::EffectParameter() + : d(new EffectParameterPrivate) +{ +} + +EffectParameter::EffectParameter(int parameterId, const QString &name, Hints hints, + const QVariant &defaultValue, const QVariant &min, const QVariant &max, + const QVariantList &values, const QString &description) + : d(new EffectParameterPrivate) +{ + d->parameterId = parameterId; + d->min = min; + d->max = max; + d->defaultValue = defaultValue; + d->name = name; + d->possibleValues = values; + d->description = description; + d->hints = hints; +} + +EffectParameter::~EffectParameter() +{ +} + +EffectParameter::EffectParameter(const EffectParameter &rhs) + : d(rhs.d) +{ +} + +EffectParameter &EffectParameter::operator=(const EffectParameter &rhs) +{ + d = rhs.d; + return *this; +} + +bool EffectParameter::operator<(const EffectParameter &rhs) const +{ + return d->parameterId < rhs.d->parameterId; +} + +bool EffectParameter::operator==(const EffectParameter &rhs) const +{ + return d->parameterId == rhs.d->parameterId; +} + +bool EffectParameter::operator>(const EffectParameter &rhs) const +{ + return d->parameterId > rhs.d->parameterId; +} + +const QString &EffectParameter::name() const +{ + return d->name; +} + +const QString &EffectParameter::description() const +{ + return d->description; +} + +bool EffectParameter::isLogarithmicControl() const +{ + return d->hints & LogarithmicHint; +} + +QVariant::Type EffectParameter::type() const +{ + if (d->possibleValues.isEmpty()) { + return d->defaultValue.type(); + } + return QVariant::String; +} + +QVariantList EffectParameter::possibleValues() const +{ + return d->possibleValues; +} + +QVariant EffectParameter::minimumValue() const +{ + return d->min; +} + +QVariant EffectParameter::maximumValue() const +{ + return d->max; +} + +QVariant EffectParameter::defaultValue() const +{ + return d->defaultValue; +} + +int EffectParameter::id() const +{ + return d->parameterId; +} + +} + +#endif //QT_NO_PHONON_EFFECT + +QT_END_NAMESPACE + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/effectparameter.h b/src/3rdparty/phonon/phonon/effectparameter.h new file mode 100644 index 0000000..4471a16 --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectparameter.h @@ -0,0 +1,237 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_EFFECTPARAMETER_H +#define PHONON_EFFECTPARAMETER_H + +#include "phonon_export.h" + +#include <QtCore/QExplicitlySharedDataPointer> +#include <QtCore/QVariant> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +namespace Phonon +{ + +class Effect; +class EffectParameterPrivate; + +/** \class EffectParameter effectparameter.h Phonon/EffectParameter + * \brief This class describes one parameter of an effect. + * + * \ingroup PhononEffects + * \author Matthias Kretz <kretz@kde.org> + * \see Effect + */ +class PHONON_EXPORT EffectParameter +{ + friend class BrightnessControl; + public: + /** + * \internal + * + * Creates an invalid effect parameter. + */ + EffectParameter(); + + /** + * The name of the parameter. Can be used as the label. + * + * \return A label for the parameter. + */ + const QString &name() const; + + /** + * The parameter may come with a description (LADSPA doesn't have a + * field for this, so don't expect many effects to provide a + * description). + * + * The description can be used for a tooltip or WhatsThis help. + * + * \return A text describing the parameter. + */ + const QString &description() const; + + /** + * Returns the parameter type. + * + * Common types are QVariant::Int, QVariant::Double, QVariant::Bool and QVariant::String. When + * QVariant::String is returned you get the possible values from possibleValues. + */ + QVariant::Type type() const; + + /** + * Returns whether the parameter should be + * displayed using a logarithmic scale. This is particularly useful for + * frequencies and gains. + */ + bool isLogarithmicControl() const; + + /** + * The minimum value to be used for the control to edit the parameter. + * + * If the returned QVariant is invalid the value is not bounded from + * below. + */ + QVariant minimumValue() const; + + /** + * The maximum value to be used for the control to edit the parameter. + * + * If the returned QVariant is invalid the value is not bounded from + * above. + */ + QVariant maximumValue() const; + + /** + * The default value. + */ + QVariant defaultValue() const; + + /** + * The possible values to be used for the control to edit the parameter. + * + * if the value of this parameter is to be picked from predefined values + * this returns the list (otherwise it returns an empty QVariantList). + */ + QVariantList possibleValues() const; + + /** + * \internal + * compares the ids of the parameters + */ + bool operator<(const EffectParameter &rhs) const; + + /** + * \internal + * compares the ids of the parameters + */ + bool operator>(const EffectParameter &rhs) const; + + /** + * \internal + * compares the ids of the parameters + */ + bool operator==(const EffectParameter &rhs) const; + + /* dtor, cctor and operator= for forward decl of EffectParameterPrivate */ + ~EffectParameter(); + EffectParameter(const EffectParameter &rhs); + EffectParameter &operator=(const EffectParameter &rhs); + + /** + * Only for backend developers: + * + * Flags to set the return values of isToggleControl(), + * isLogarithmicControl(), isIntegerControl(), isBoundedBelow() and + * isBoundedAbove(). The values of the flags correspond to the values + * used for LADSPA effects. + */ + enum Hint { + /** + * If this hint is set it means that + * the the control has only two states: zero and non-zero. + * + * \see isToggleControl() + */ + ToggledHint = 0x04, + + /* LADSPA's SAMPLE_RATE hint needs to be translated by the backend + * to normal bounds, as the backend knows the sample rate - and the + * frontend doesn't */ + + /** + * \see isLogarithmicControl() + */ + LogarithmicHint = 0x10, + /** + * \see isIntegerControl + */ + IntegerHint = 0x20 + }; + Q_DECLARE_FLAGS(Hints, Hint) + + /** + * Only to be used by backend implementations: + * + * Creates a new effect parameter. + * + * \param parameterId This is a number to uniquely identify the + * parameter. The id is used for value() and setValue(). + * + * \param name The name/label for this parameter. + * + * \param hints Sets the hints for the type of parameter. + * + * \param defaultValue The value that should be used as a default. + * + * \param min The minimum value allowed for this parameter. You only + * need to set this if the BoundedBelowHint is set. + * + * \param max The maximum value allowed for this parameter. You only + * need to set this if the BoundedAboveHint is set. + * + * \param description A descriptive text for the parameter + * (explaining what it controls) to be used as a tooltip or + * WhatsThis help. + */ + EffectParameter(int parameterId, const QString &name, Hints hints, + const QVariant &defaultValue, const QVariant &min = QVariant(), + const QVariant &max = QVariant(), const QVariantList &values = QVariantList(), + const QString &description = QString()); + + /** + * \internal + * + * Returns the parameter's id. + */ + int id() const; + + protected: + /** + * The data is implicitly shared. + */ + QExplicitlySharedDataPointer<EffectParameterPrivate> d; +}; + +uint PHONON_EXPORT qHash(const Phonon::EffectParameter ¶m); + +} // namespace Phonon + +#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 +//this ensures that code outside Phonon can use the hash function +//it also a workaround for some compilers +inline uint qHash(const Phonon::EffectParameter ¶m) { return Phonon::qHash(param); } //krazy:exclude=inline +#endif +Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::EffectParameter::Hints) + +#endif //QT_NO_PHONON_EFFECT + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_EFFECTPARAMETER_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/effectparameter_p.h b/src/3rdparty/phonon/phonon/effectparameter_p.h new file mode 100644 index 0000000..f3f9f88 --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectparameter_p.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef EFFECTPARAMETER_P_H +#define EFFECTPARAMETER_P_H + +#include "effectparameter.h" +#include <QtCore/QSharedData> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECT + +namespace Phonon +{ + +class EffectParameterPrivate : public QSharedData +{ + public: + int parameterId; + QVariant min; + QVariant max; + QVariant defaultValue; + QString name; + QString description; + QVariantList possibleValues; + EffectParameter::Hints hints; +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_EFFECT + +QT_END_NAMESPACE + +#endif // EFFECTPARAMETER_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp new file mode 100644 index 0000000..edcbe1f --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectwidget.cpp @@ -0,0 +1,259 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "effectwidget.h" +#include "effectwidget_p.h" + +#include <QtCore/QtAlgorithms> +#include <QtCore/QList> + +#include "effect.h" +#include "effectparameter.h" +#include "phonondefs_p.h" +#include <QtGui/QBoxLayout> +#include <QtGui/QLabel> +#include <QtGui/QSpinBox> +#include <QtGui/QCheckBox> +#include <QtGui/QComboBox> +#include <QtGui/QSlider> +#include <limits> + +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif +static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min(); +static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max(); +static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min(); +static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max(); +static const int SLIDER_RANGE = 8; +static const int TICKINTERVAL = 4; + + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECTWIDGET + +namespace Phonon +{ + +EffectWidget::EffectWidget(Effect *effect, QWidget *parent) + : QWidget(parent), + k_ptr(new EffectWidgetPrivate(effect)) +{ + K_D(EffectWidget); + d->q_ptr = this; + d->autogenerateUi(); +} + +EffectWidget::~EffectWidget() +{ + delete k_ptr; +} + +/* +EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent) + : QWidget(parent) + , k_ptr(&dd) +{ + K_D(EffectWidget); + d->q_ptr = this; + d->autogenerateUi(); +} +*/ + +EffectWidgetPrivate::EffectWidgetPrivate(Effect *e) + : effect(e) +{ + //TODO: look up whether there is a specialized widget for this effect. This + //could be a DSO or a Designer ui file found via KTrader. + // + //if no specialized widget is available: +} + +void EffectWidgetPrivate::autogenerateUi() +{ + Q_Q(EffectWidget); + QVBoxLayout *mainLayout = new QVBoxLayout(q); + mainLayout->setMargin(0); + const QList<Phonon::EffectParameter> parameters = effect->parameters(); + for (int i = 0; i < parameters.count(); ++i) { + const EffectParameter ¶ = parameters.at(i); + QVariant value = effect->parameterValue(para); + QHBoxLayout *pLayout = new QHBoxLayout; + mainLayout->addLayout(pLayout); + + QLabel *label = new QLabel(q); + pLayout->addWidget(label); + label->setText(para.name()); +#ifndef QT_NO_TOOLTIP + label->setToolTip(para.description()); +#endif + + QWidget *control = 0; + switch (int(para.type())) { + case QVariant::String: + { + QComboBox *cb = new QComboBox(q); + control = cb; + if (value.type() == QVariant::Int) { + //value just defines the item index + for (int i = 0; i < para.possibleValues().count(); ++i) { + cb->addItem(para.possibleValues().at(i).toString()); + } + cb->setCurrentIndex(value.toInt()); + QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int))); + } else { + for (int i = 0; i < para.possibleValues().count(); ++i) { + const QVariant &item = para.possibleValues().at(i); + cb->addItem(item.toString()); + if (item == value) { + cb->setCurrentIndex(cb->count() - 1); + } + } + QObject::connect(cb, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_setStringParameter(QString))); + } + } + break; + case QVariant::Bool: + { + QCheckBox *cb = new QCheckBox(q); + control = cb; + cb->setChecked(value.toBool()); + QObject::connect(cb, SIGNAL(toggled(bool)), q, SLOT(_k_setToggleParameter(bool))); + } + break; + case QVariant::Int: + { + QSpinBox *sb = new QSpinBox(q); + control = sb; + bool minValueOk = false; + bool maxValueOk = false; + const int minValue = para.minimumValue().toInt(&minValueOk); + const int maxValue = para.maximumValue().toInt(&maxValueOk); + + sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT); + sb->setValue(value.toInt()); + QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int))); + } + break; + case QMetaType::Float: + case QVariant::Double: + { + const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ? + para.minimumValue().toReal() : DEFAULT_MIN; + const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ? + para.maximumValue().toReal() : DEFAULT_MAX; + + if (minValue == -1. && maxValue == 1.) { + //Special case values between -1 and 1.0 to use a slider for improved usability + QSlider *slider = new QSlider(Qt::Horizontal, q); + control = slider; + slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE); + slider->setValue(int(SLIDER_RANGE * value.toReal())); + slider->setTickPosition(QSlider::TicksBelow); + slider->setTickInterval(TICKINTERVAL); + QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int))); + } else { + double step = 0.1; + if (qAbs(maxValue - minValue) > 50) + step = 1.0; + QDoubleSpinBox *sb = new QDoubleSpinBox(q); + control = sb; + sb->setRange(minValue, maxValue); + sb->setValue(value.toDouble()); + sb->setSingleStep(step); + QObject::connect(sb, SIGNAL(valueChanged(double)), q, + SLOT(_k_setDoubleParameter(double))); + } + } + break; + default: + break; + } + + if (control) { +#ifndef QT_NO_TOOLTIP + control->setToolTip(para.description()); +#endif +#ifndef QT_NO_SHORTCUT + label->setBuddy(control); +#endif + pLayout->addWidget(control); + parameterForObject.insert(control, para); + } + } +} + +void EffectWidgetPrivate::_k_setToggleParameter(bool checked) +{ + Q_Q(EffectWidget); + if (parameterForObject.contains(q->sender())) { + effect->setParameterValue(parameterForObject[q->sender()], checked); + } +} + +void EffectWidgetPrivate::_k_setIntParameter(int value) +{ + Q_Q(EffectWidget); + if (parameterForObject.contains(q->sender())) { + effect->setParameterValue(parameterForObject[q->sender()], value); + } +} + +void EffectWidgetPrivate::_k_setDoubleParameter(double value) +{ + Q_Q(EffectWidget); + if (parameterForObject.contains(q->sender())) { + effect->setParameterValue(parameterForObject[q->sender()], value); + } +} + +void EffectWidgetPrivate::_k_setStringParameter(const QString &value) +{ + Q_Q(EffectWidget); + if (parameterForObject.contains(q->sender())) { + effect->setParameterValue(parameterForObject[q->sender()], value); + } +} + +void EffectWidgetPrivate::_k_setSliderParameter(int value) +{ + Q_Q(EffectWidget); + if (parameterForObject.contains(q->sender())) { + effect->setParameterValue(parameterForObject[q->sender()], double(value) / double(SLIDER_RANGE)); + } +} + + +} // namespace Phonon + + +#endif // QT_NO_PHONON_EFFECTWIDGET + +QT_END_NAMESPACE + +#include "moc_effectwidget.cpp" + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/effectwidget.h b/src/3rdparty/phonon/phonon/effectwidget.h new file mode 100644 index 0000000..17a310f --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectwidget.h @@ -0,0 +1,76 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_UI_EFFECTWIDGET_H +#define PHONON_UI_EFFECTWIDGET_H + +#include "phonon_export.h" +#include "phonondefs.h" +#include <QtGui/QWidget> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECTWIDGET + +namespace Phonon +{ +class Effect; + + class EffectWidgetPrivate; + + /** \class EffectWidget effectwidget.h Phonon/EffectWidget + * \brief Widget to control the parameters of an Effect. + * + * \ingroup PhononWidgets + * \ingroup PhononEffects + * \author Matthias Kretz <kretz@kde.org> + */ + class PHONON_EXPORT EffectWidget : public QWidget + { + Q_OBJECT + K_DECLARE_PRIVATE(EffectWidget) + public: + explicit EffectWidget(Effect *effect, QWidget *parent = 0); + ~EffectWidget(); + + protected: + //EffectWidget(EffectWidgetPrivate &dd, QWidget *parent); + EffectWidgetPrivate *const k_ptr; + + private: + Q_PRIVATE_SLOT(k_func(), void _k_setToggleParameter(bool checked)) + Q_PRIVATE_SLOT(k_func(), void _k_setIntParameter(int value)) + Q_PRIVATE_SLOT(k_func(), void _k_setDoubleParameter(double value)) + Q_PRIVATE_SLOT(k_func(), void _k_setStringParameter(const QString &)) + Q_PRIVATE_SLOT(k_func(), void _k_setSliderParameter(int)) + }; +} // namespace Phonon + +#endif //QT_NO_PHONON_EFFECTWIDGET + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_UI_EFFECTWIDGET_H + +// vim: sw=4 ts=4 tw=100 diff --git a/src/3rdparty/phonon/phonon/effectwidget_p.h b/src/3rdparty/phonon/phonon/effectwidget_p.h new file mode 100644 index 0000000..aad422a --- /dev/null +++ b/src/3rdparty/phonon/phonon/effectwidget_p.h @@ -0,0 +1,64 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_UI_EFFECTWIDGET_P_H +#define PHONON_UI_EFFECTWIDGET_P_H + +#include "effectwidget.h" +#include "effectparameter.h" +#include <QtCore/QHash> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_EFFECTWIDGET + +namespace Phonon +{ + class EffectWidgetPrivate + { + Q_DECLARE_PUBLIC(EffectWidget) + protected: + EffectWidgetPrivate(Effect *effect); + + EffectWidget *q_ptr; + + private: + Effect *effect; + QHash<QObject *, EffectParameter> parameterForObject; + + void _k_setToggleParameter(bool checked); + void _k_setIntParameter(int value); + void _k_setDoubleParameter(double value); + void _k_setStringParameter(const QString &); + void _k_setSliderParameter(int); + + void autogenerateUi(); + }; +} // namespace Phonon + +#endif //QT_NO_PHONON_EFFECTWIDGET + +QT_END_NAMESPACE + +#endif // PHONON_UI_EFFECTWIDGET_P_H + +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/extractmethodcalls.rb b/src/3rdparty/phonon/phonon/extractmethodcalls.rb new file mode 100755 index 0000000..9100489 --- /dev/null +++ b/src/3rdparty/phonon/phonon/extractmethodcalls.rb @@ -0,0 +1,527 @@ +#!/usr/bin/ruby + +class MethodDef + def initialize(returnType, signature, optional) + @returnType = returnType + @signature = signature + @optional = optional + end + + attr_reader :returnType, :signature, :optional + attr_writer :optional +end + +class SignalDef + def initialize(signature) + @signature = signature + end + + attr_reader :signature +end + +class Parser + def initialize(filename) + @file = File.new filename, "r" + @signatures = Hash.new + parse + end + + attr_reader :signatures + + private + def addSignal(signature) + unless @signatures.include? signature + @signatures[signature] = SignalDef.new(signature) + end + end + + def addMethod(returnType, signature, optional) + if @signatures.include? signature + if returnType != '' + if @signatures[signature].returnType == '' + optional = false if @signatures[signature].optional == false + @signatures[signature] = MethodDef.new(returnType, signature, optional) + elsif @signatures[signature].returnType != returnType + fail "same signature '#{signature}' but differing return types: #{returnType} and #{@signatures[signature].returnType}" + end + elsif not optional and @signatures[signature].optional + @signatures[signature].optional = false + end + else + @signatures[signature] = MethodDef.new(returnType, signature, optional) + end + end + + PARSER_RETURN_TYPE = 0 + PARSER_RETURN_VAR = 1 + PARSER_METHOD_NAME = 2 + PARSER_ARGUMENT_TYPE = 3 + PARSER_ARGUMENT_VAR = 4 + + PARSER2_CLASSNAME = 0 + PARSER2_METHODPREFIX = 1 + + PARSER3_QMETAOBJECT = 0 + PARSER3_SCOPEDELIMIT = 1 + PARSER3_INVOKEMETHOD = 2 + PARSER3_OPENPARENTH = 3 + PARSER3_BACKENDOBJ = 4 + PARSER3_METHODNAME = 5 + PARSER3_CONNECTION = 6 + PARSER3_RET_OR_ARG = 7 + PARSER3_RET_OPEN = 8 + PARSER3_RET_TYPE = 9 + PARSER3_RET_NAME = 10 + PARSER3_RET_CLOSE = 11 + PARSER3_ARG = 12 + PARSER3_ARG_OPEN = 13 + PARSER3_ARG_TYPE = 14 + PARSER3_ARG_NAME = 15 + PARSER3_ARG_CLOSE = 16 + PARSER3_CLOSE = 17 + PARSER3_DONE = 18 + + PARSER4_OPENING_PAREN = 0 + PARSER4_SENDER = 1 + PARSER4_PRIVATE_SENDER = 2 + PARSER4_COMMA_1 = 3 + PARSER4_SIGNAL_MACRO = 4 + PARSER4_SIGNAL_OPENING_PAREN = 5 + PARSER4_SIGNAL_SIGNATURE = 6 + PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN = 7 + PARSER4_SIGNAL_SIGNATURE_CONST = 8 + PARSER4_SIGNAL_SIGNATURE_TYPE1 = 9 + PARSER4_SIGNAL_SIGNATURE_TYPE2_1 = 10 + PARSER4_SIGNAL_SIGNATURE_TYPE2_2 = 11 + PARSER4_SIGNAL_CLOSING_PAREN = 12 + + def parse + inbackendcall = false + innamedescriptioncall = false + ininvokemethodcall = false + invokemethodcallOnBackendObject = false + inconnect = false + optionalmethod = false + lasttoken = ';' + thistoken = ';' + returnType = String.new + signature = String.new + parserstate = PARSER_RETURN_TYPE + depth = 0 + tokenize do |token| + #STDERR.puts token + lasttoken = thistoken + thistoken = token + token = token[1..-1] if token[0,9] == "pBACKEND_" + if token[0,8] == "BACKEND_" + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + inbackendcall = true + if token[8,3] != "GET" # skip return arg + parserstate = PARSER_METHOD_NAME + returnType = '' + else + parserstate = PARSER_RETURN_TYPE + end + elsif token == 'NAMEDESCRIPTIONFROMINDEX' + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + innamedescriptioncall = true + parserstate = PARSER2_CLASSNAME + elsif token == 'QMetaObject' + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + ininvokemethodcall = true + parserstate = PARSER3_SCOPEDELIMIT + optionalmethod = (lasttoken[-1,1] == '=' or lasttoken == '(' or lasttoken == '!') ? true : false + elsif token == 'connect' + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + inconnect = true + parserstate = PARSER4_OPENING_PAREN + elsif inconnect + #puts "state = #{parserstate}, token = #{token}" + lastparserstate = parserstate + case parserstate + when PARSER4_OPENING_PAREN + parserstate = PARSER4_SENDER if token == '(' + when PARSER4_SENDER + # d->m_backendObject or only m_backendObject + parserstate = PARSER4_COMMA_1 if token == 'm_backendObject' + parserstate = PARSER4_PRIVATE_SENDER if token == 'd' + when PARSER4_PRIVATE_SENDER + parserstate = PARSER4_SENDER if token == '->' + when PARSER4_COMMA_1 + parserstate = PARSER4_SIGNAL_MACRO if token == ',' + when PARSER4_SIGNAL_MACRO + parserstate = PARSER4_SIGNAL_OPENING_PAREN if token == 'SIGNAL' + when PARSER4_SIGNAL_OPENING_PAREN + parserstate = PARSER4_SIGNAL_SIGNATURE if token == '(' + when PARSER4_SIGNAL_SIGNATURE + signature = token + parserstate = PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN + when PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN + case token + when '(' + signature += '(' + parserstate = PARSER4_SIGNAL_SIGNATURE_CONST + when '()' + signature += '()' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + end + when PARSER4_SIGNAL_SIGNATURE_CONST + case token + when 'const' + signature += 'const ' + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1 + when ')' + signature += ')' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + end + when PARSER4_SIGNAL_SIGNATURE_TYPE1 + case token + when 'const' + when ')' + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + end + when PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + case token + when ',' + signature += ', ' + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1 + when ')' + signature += ')' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_2 + end + when PARSER4_SIGNAL_SIGNATURE_TYPE2_2 + case token + when ',' + signature += ', ' + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1 + when ')' + signature += ')' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + end + when PARSER4_SIGNAL_CLOSING_PAREN + addSignal(signature) if token == ')' + end + if parserstate == lastparserstate + inconnect = false + signature = String.new + end + elsif ininvokemethodcall + case parserstate + when PARSER3_BACKENDOBJ + if token == ',' + if invokemethodcallOnBackendObject + parserstate += 1 + else + ininvokemethodcall = false + end + elsif token =~ /backendObject/ + invokemethodcallOnBackendObject = true + end + when PARSER3_SCOPEDELIMIT + if token == '::' + parserstate += 1 + else + ininvokemethodcall = false + end + when PARSER3_INVOKEMETHOD + if token == 'invokeMethod' + parserstate += 1 + else + ininvokemethodcall = false + end + when PARSER3_OPENPARENTH + fail if token != '(' + parserstate += 1 + invokemethodcallOnBackendObject = false + when PARSER3_METHODNAME + case token + when ',' + signature += '(' + parserstate = PARSER3_CONNECTION + else + fail if signature.length > 0 + signature = token[1..-2] + end + when PARSER3_CONNECTION + case token + when ',' + parserstate = PARSER3_RET_OR_ARG + when ')' + parserstate = PARSER3_CLOSE +# the connection is optional + when 'Q_RETURN_ARG' + parserstate = PARSER3_RET_OPEN + when 'Q_ARG' + returnType = '' + parserstate = PARSER3_ARG_OPEN + end + when PARSER3_RET_OR_ARG + if token == 'Q_RETURN_ARG' + parserstate = PARSER3_RET_OPEN + elsif token == 'Q_ARG' + returnType = '' + parserstate = PARSER3_ARG_OPEN + else + fail "unexpected token '#{token}" + end + when PARSER3_RET_TYPE + if token == ',' + parserstate += 1 + else + if token == '*' or token == '&' or token == '<' or token == '>' or token == '::' or returnType.empty? or returnType[-1,1] == '<' or returnType[-2,2] == '::' + returnType += token + else + returnType += ' ' + token + end + end + when PARSER3_RET_NAME + parserstate = PARSER3_RET_CLOSE if token == ')' + when PARSER3_RET_CLOSE + case token + when ')' + parserstate = PARSER3_CLOSE + when ',' + parserstate = PARSER3_ARG + end + when PARSER3_ARG + if token == 'Q_ARG' + parserstate = PARSER3_ARG_OPEN + else + fail "unexpected token '#{token}" + end + when PARSER3_ARG_TYPE + if token == ',' + parserstate += 1 + else + signature += ' ' if signature[-1,1] =~ /\w/ and token[0,1] =~ /\w/ + signature += token + end + when PARSER3_ARG_NAME + case token + when '(' + depth += 1 + when ')' + if depth == 0 + parserstate = PARSER3_ARG_CLOSE + else + depth -= 1 + end + end + when PARSER3_ARG_CLOSE + case token + when ',' + signature += ',' + parserstate = PARSER3_ARG + when ')' + parserstate = PARSER3_CLOSE + else + fail + end + when PARSER3_ARG_OPEN, PARSER3_RET_OPEN + fail if token != '(' + parserstate += 1 + when PARSER3_CLOSE + signature += ')' + addMethod returnType, signature, optionalmethod + ininvokemethodcall = false + returnType = String.new + signature = String.new + end + elsif innamedescriptioncall + case parserstate + when PARSER2_CLASSNAME + parserstate = PARSER2_METHODPREFIX if token == ',' + when PARSER2_METHODPREFIX + addMethod 'QSet<int>', token + 'Indexes()', false + addMethod 'int', token + 'Name()', false + addMethod 'int', token + 'Description()', false + innamedescriptioncall = false + end + elsif inbackendcall + next if token == '(' # skip ( + if token == ';' + if signature.length > 0 + signature += ')' + addMethod returnType, signature, false + signature = String.new + returnType = String.new + end + inbackendcall = false + else + if token == ',' + if parserstate == PARSER_ARGUMENT_VAR + signature += ',' + parserstate = PARSER_ARGUMENT_TYPE + else + parserstate += 1 + end + next + end + case parserstate + when PARSER_RETURN_TYPE + returnType += token + when PARSER_RETURN_VAR + when PARSER_METHOD_NAME + next if token == ')' + fail if token[0,1] != '"' or token[-1,1] != '"' + fail if signature.length > 0 + signature = token[1..-2] + '(' + when PARSER_ARGUMENT_TYPE + signature += token + end + end + end + end + end + + def tokenize + incomment = false + instring = false + laststring = '' + linenum = 0 + @file.each_line do |line| + linenum += 1 + line.strip! + next if line[0..1] == "//" + next if line[0,1] == "#" # ignore preprocessor statements + line.split(/(\b|\s+)/).each do |token| + #STDERR.puts "string: #{instring} comment: #{incomment} token: '#{token}'" + if instring + indexOfEscapedQuote = token.index '\\"' + if indexOfEscapedQuote != nil + laststring += token + next + end + indexOfQuote = token.index '"' + if indexOfQuote and indexOfQuote > 0 + fail if token[indexOfQuote-1,1] == '\\' + laststring += token[0..indexOfQuote-1] + token = token[indexOfQuote..-1] + end + if token[0,2] == '""' + laststring += token[2..-1] + next + elsif token[0,1] == '"' + if laststring[-1,1] == '\\' + laststring[-1,1] = '"' + laststring += token[1..-1] + next + end + instring = false + yield laststring + '"' + token = token[1..-1] + else + laststring += token + next + end + end + token.strip! + next if token.empty? + if incomment + incomment = false if token[0..1] == "*/" + next + else + if token[0..1] == "/*" + incomment = true + next + end + break if token == "//" + end + doublequote = token.index '""' + if doublequote != nil + if doublequote > 0 + yield token[0,doublequote] + end + yield '""' + if token.length > doublequote+2 + token = token[doublequote+2..-1] + else + next + end + end + quote = token.index '"' + if quote != nil + laststring = token[quote..-1] + instring = true + if quote > 0 + token = token[0,quote] + else + next + end + end + semicolon = token.index ';' + if not semicolon + tokenize2(token) { |i| yield i } + elsif semicolon > 0 + tokenize2(token[0..semicolon-1]) { |i| yield i } + yield ';' + if token.length > semicolon + 1 + tokenize2(token[semicolon+1..-1]) { |i| yield i } + end + elsif (semicolon == 0 and token.length > 1) + yield ';' + tokenize2(token[1..-1]) { |i| yield i } + else + yield token # a single ; + end + end + end + end + + def tokenize2(token) + if token.length > 1 + #STDERR.puts "long token: #{token}" + while token[0,1] == '(' or token[0,1] == ')' or token[0,1] == "'" or token[0,1] == '&' + yield token[0,1] + token = token[1..-1] + #STDERR.puts "less long token: #{token}" + end + return if token.empty? + if token.length == 1 + yield token + return + elsif token[-1,1] == ',' or token[-1,1] == "'" + yield token[0..-2] + yield token[-1,1] + return + end + end + yield token + end +end + +p = Parser.new ARGV[0] +p.signatures.each do |signature,method| + if method.class == SignalDef + puts "addSignal(\"#{signature}\");" + else + if method.optional + puts "addMethod(\"#{method.returnType}\", \"#{signature}\", true);" + else + puts "addMethod(\"#{method.returnType}\", \"#{signature}\");" + end + end +end diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp new file mode 100644 index 0000000..b5e565b --- /dev/null +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -0,0 +1,474 @@ +/* This file is part of the KDE project + Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "factory_p.h" + +#include "backendinterface.h" +#include "medianode_p.h" +#include "mediaobject.h" +#include "audiooutput.h" +#include "globalstatic_p.h" +#include "objectdescription.h" +#include "platformplugin.h" +#include "phononnamespace_p.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QList> +#include <QtCore/QPluginLoader> +#include <QtCore/QPointer> +#ifndef QT_NO_DBUS +#include <QtDBus/QtDBus> +#endif + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +class PlatformPlugin; +class FactoryPrivate : public Phonon::Factory::Sender +{ + friend QObject *Factory::backend(bool); + Q_OBJECT + public: + FactoryPrivate(); + ~FactoryPrivate(); + bool createBackend(); +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + PlatformPlugin *platformPlugin(); + + PlatformPlugin *m_platformPlugin; + bool m_noPlatformPlugin; +#endif //QT_NO_PHONON_PLATFORMPLUGIN + QPointer<QObject> m_backendObject; + + QList<QObject *> objects; + QList<MediaNodePrivate *> mediaNodePrivateList; + + private Q_SLOTS: + /** + * This is called via DBUS when the user changes the Phonon Backend. + */ +#ifndef QT_NO_DBUS + void phononBackendChanged(); +#endif //QT_NO_DBUS + + /** + * unregisters the backend object + */ + void objectDestroyed(QObject *); + + void objectDescriptionChanged(ObjectDescriptionType); +}; + +PHONON_GLOBAL_STATIC(Phonon::FactoryPrivate, globalFactory) + +static inline void ensureLibraryPathSet() +{ +#ifdef PHONON_LIBRARY_PATH + static bool done = false; + if (!done) { + done = true; + QCoreApplication::addLibraryPath(QLatin1String(PHONON_LIBRARY_PATH)); + } +#endif // PHONON_LIBRARY_PATH +} + +void Factory::setBackend(QObject *b) +{ + Q_ASSERT(globalFactory->m_backendObject == 0); + globalFactory->m_backendObject = b; +} + +/*void Factory::createBackend(const QString &library, const QString &version) +{ + Q_ASSERT(globalFactory->m_backendObject == 0); + PlatformPlugin *f = globalFactory->platformPlugin(); + if (f) { + globalFactory->m_backendObject = f->createBackend(library, version); + } +}*/ + +bool FactoryPrivate::createBackend() +{ +#ifndef QT_NO_LIBRARY + Q_ASSERT(m_backendObject == 0); +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + PlatformPlugin *f = globalFactory->platformPlugin(); + if (f) { + m_backendObject = f->createBackend(); + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + if (!m_backendObject) { + ensureLibraryPathSet(); + + // could not load a backend through the platform plugin. Falling back to the default + // (finding the first loadable backend). + const QLatin1String suffix("/phonon_backend/"); + const QStringList paths = QCoreApplication::libraryPaths(); + for (int i = 0; i < paths.count(); ++i) { + const QString libPath = paths.at(i) + suffix; + const QDir dir(libPath); + if (!dir.exists()) { + pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist"; + continue; + } + + QStringList plugins(dir.entryList(QDir::Files)); + +#ifdef Q_OS_SYMBIAN + static const QString preferredPluginName = QLatin1String("phonon_mmf"); + const int preferredPluginIndex = plugins.indexOf(preferredPluginName + ".qtplugin"); + if (preferredPluginIndex != -1) + plugins.move(preferredPluginIndex, 0); +#endif + + const QStringList files = dir.entryList(QDir::Files); + for (int i = 0; i < plugins.count(); ++i) { + QPluginLoader pluginLoader(libPath + plugins.at(i)); + if (!pluginLoader.load()) { + pDebug() << Q_FUNC_INFO << " load failed:" + << pluginLoader.errorString(); + continue; + } + pDebug() << pluginLoader.instance(); + m_backendObject = pluginLoader.instance(); + if (m_backendObject) { + break; + } + + // no backend found, don't leave an unused plugin in memory + pluginLoader.unload(); + } + + if (m_backendObject) { + break; + } + } + if (!m_backendObject) { + pWarning() << Q_FUNC_INFO << "phonon backend plugin could not be loaded"; + return false; + } + } + + connect(m_backendObject, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), + SLOT(objectDescriptionChanged(ObjectDescriptionType))); + + return true; +#else //QT_NO_LIBRARY + pWarning() << Q_FUNC_INFO << "Trying to use Phonon with QT_NO_LIBRARY defined. " + "That is currently not supported"; + return false; +#endif +} + +FactoryPrivate::FactoryPrivate() + : +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + m_platformPlugin(0), + m_noPlatformPlugin(false), +#endif //QT_NO_PHONON_PLATFORMPLUGIN + m_backendObject(0) +{ + // Add the post routine to make sure that all other global statics (especially the ones from Qt) + // are still available. If the FactoryPrivate dtor is called too late many bad things can happen + // as the whole backend might still be alive. + qAddPostRoutine(globalFactory.destroy); +#ifndef QT_NO_DBUS + QDBusConnection::sessionBus().connect(QString(), QString(), QLatin1String("org.kde.Phonon.Factory"), + QLatin1String("phononBackendChanged"), this, SLOT(phononBackendChanged())); +#endif +} + +FactoryPrivate::~FactoryPrivate() +{ + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->deleteBackendObject(); + } + if (objects.size() > 0) { + pError() << "The backend objects are not deleted as was requested."; + qDeleteAll(objects); + } + delete m_backendObject; +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + delete m_platformPlugin; +#endif //QT_NO_PHONON_PLATFORMPLUGIN +} + +void FactoryPrivate::objectDescriptionChanged(ObjectDescriptionType type) +{ +#ifdef PHONON_METHODTEST + Q_UNUSED(type); +#else + pDebug() << Q_FUNC_INFO << type; + switch (type) { + case AudioOutputDeviceType: + emit availableAudioOutputDevicesChanged(); + break; + case AudioCaptureDeviceType: + emit availableAudioCaptureDevicesChanged(); + break; + default: + break; + } + //emit capabilitiesChanged(); +#endif // PHONON_METHODTEST +} + +Factory::Sender *Factory::sender() +{ + return globalFactory; +} + +bool Factory::isMimeTypeAvailable(const QString &mimeType) +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + PlatformPlugin *f = globalFactory->platformPlugin(); + if (f) { + return f->isMimeTypeAvailable(mimeType); + } +#else + Q_UNUSED(mimeType); +#endif //QT_NO_PHONON_PLATFORMPLUGIN + return true; // the MIME type might be supported, let BackendCapabilities find out +} + +void Factory::registerFrontendObject(MediaNodePrivate *bp) +{ + globalFactory->mediaNodePrivateList.prepend(bp); // inserted last => deleted first +} + +void Factory::deregisterFrontendObject(MediaNodePrivate *bp) +{ + // The Factory can already be cleaned up while there are other frontend objects still alive. + // When those are deleted they'll call deregisterFrontendObject through ~BasePrivate + if (!globalFactory.isDestroyed()) { + globalFactory->mediaNodePrivateList.removeAll(bp); + } +} + +#ifndef QT_NO_DBUS +void FactoryPrivate::phononBackendChanged() +{ + if (m_backendObject) { + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->deleteBackendObject(); + } + if (objects.size() > 0) { + pDebug() << "WARNING: we were asked to change the backend but the application did\n" + "not free all references to objects created by the factory. Therefore we can not\n" + "change the backend without crashing. Now we have to wait for a restart to make\n" + "backendswitching possible."; + // in case there were objects deleted give 'em a chance to recreate + // them now + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->createBackendObject(); + } + return; + } + delete m_backendObject; + m_backendObject = 0; + } + createBackend(); + for (int i = 0; i < mediaNodePrivateList.count(); ++i) { + mediaNodePrivateList.at(i)->createBackendObject(); + } + emit backendChanged(); +} +#endif //QT_NO_DBUS + +//X void Factory::freeSoundcardDevices() +//X { +//X if (globalFactory->backend) { +//X globalFactory->backend->freeSoundcardDevices(); +//X } +//X } + +void FactoryPrivate::objectDestroyed(QObject * obj) +{ + //pDebug() << Q_FUNC_INFO << obj; + objects.removeAll(obj); +} + +#define FACTORY_IMPL(classname) \ +QObject *Factory::create ## classname(QObject *parent) \ +{ \ + if (backend()) { \ + return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent)); \ + } \ + return 0; \ +} +#define FACTORY_IMPL_1ARG(classname) \ +QObject *Factory::create ## classname(int arg1, QObject *parent) \ +{ \ + if (backend()) { \ + return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent, QList<QVariant>() << arg1)); \ + } \ + return 0; \ +} + +FACTORY_IMPL(MediaObject) +#ifndef QT_NO_PHONON_EFFECT +FACTORY_IMPL_1ARG(Effect) +#endif //QT_NO_PHONON_EFFECT +#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT +FACTORY_IMPL(VolumeFaderEffect) +#endif //QT_NO_PHONON_VOLUMEFADEREFFECT +FACTORY_IMPL(AudioOutput) +#ifndef QT_NO_PHONON_VIDEO +FACTORY_IMPL(VideoWidget) +#endif //QT_NO_PHONON_VIDEO +FACTORY_IMPL(AudioDataOutput) + +#undef FACTORY_IMPL + +#ifndef QT_NO_PHONON_PLATFORMPLUGIN +PlatformPlugin *FactoryPrivate::platformPlugin() +{ + if (m_platformPlugin) { + return m_platformPlugin; + } + if (m_noPlatformPlugin) { + return 0; + } +#ifndef QT_NO_DBUS + if (!QCoreApplication::instance() || QCoreApplication::applicationName().isEmpty()) { + pWarning() << "Phonon needs QCoreApplication::applicationName to be set to export audio output names through the DBUS interface"; + } +#endif + Q_ASSERT(QCoreApplication::instance()); + const QByteArray platform_plugin_env = qgetenv("PHONON_PLATFORMPLUGIN"); + if (!platform_plugin_env.isEmpty()) { + QPluginLoader pluginLoader(QString::fromLocal8Bit(platform_plugin_env.constData())); + if (pluginLoader.load()) { + m_platformPlugin = qobject_cast<PlatformPlugin *>(pluginLoader.instance()); + if (m_platformPlugin) { + return m_platformPlugin; + } + } + } + const QString suffix(QLatin1String("/phonon_platform/")); + ensureLibraryPathSet(); + QDir dir; + dir.setNameFilters( + !qgetenv("KDE_FULL_SESSION").isEmpty() ? QStringList(QLatin1String("kde.*")) : + (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty() ? QStringList(QLatin1String("gnome.*")) : + QStringList()) + ); + dir.setFilter(QDir::Files); + const QStringList libPaths = QCoreApplication::libraryPaths(); + forever { + for (int i = 0; i < libPaths.count(); ++i) { + const QString libPath = libPaths.at(i) + suffix; + dir.setPath(libPath); + if (!dir.exists()) { + continue; + } + const QStringList files = dir.entryList(QDir::Files); + for (int i = 0; i < files.count(); ++i) { + QPluginLoader pluginLoader(libPath + files.at(i)); + if (!pluginLoader.load()) { + pDebug() << Q_FUNC_INFO << " platform plugin load failed:" + << pluginLoader.errorString(); + continue; + } + pDebug() << pluginLoader.instance(); + QObject *qobj = pluginLoader.instance(); + m_platformPlugin = qobject_cast<PlatformPlugin *>(qobj); + pDebug() << m_platformPlugin; + if (m_platformPlugin) { + connect(qobj, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), + SLOT(objectDescriptionChanged(ObjectDescriptionType))); + return m_platformPlugin; + } else { + delete qobj; + pDebug() << Q_FUNC_INFO << dir.absolutePath() << "exists but the platform plugin was not loadable:" << pluginLoader.errorString(); + pluginLoader.unload(); + } + } + } + if (dir.nameFilters().isEmpty()) { + break; + } + dir.setNameFilters(QStringList()); + } + pDebug() << Q_FUNC_INFO << "platform plugin could not be loaded"; + m_noPlatformPlugin = true; + return 0; +} + +PlatformPlugin *Factory::platformPlugin() +{ + return globalFactory->platformPlugin(); +} +#endif // QT_NO_PHONON_PLATFORMPLUGIN + +QObject *Factory::backend(bool createWhenNull) +{ + if (globalFactory.isDestroyed()) { + return 0; + } + if (createWhenNull && globalFactory->m_backendObject == 0) { + globalFactory->createBackend(); + // XXX: might create "reentrancy" problems: + // a method calls this method and is called again because the + // backendChanged signal is emitted + emit globalFactory->backendChanged(); + } + return globalFactory->m_backendObject; +} + +#ifndef QT_NO_PROPERTIES +#define GET_STRING_PROPERTY(name) \ +QString Factory::name() \ +{ \ + if (globalFactory->m_backendObject) { \ + return globalFactory->m_backendObject->property(#name).toString(); \ + } \ + return QString(); \ +} \ + +GET_STRING_PROPERTY(identifier) +GET_STRING_PROPERTY(backendName) +GET_STRING_PROPERTY(backendComment) +GET_STRING_PROPERTY(backendVersion) +GET_STRING_PROPERTY(backendIcon) +GET_STRING_PROPERTY(backendWebsite) +#endif //QT_NO_PROPERTIES +QObject *Factory::registerQObject(QObject *o) +{ + if (o) { + QObject::connect(o, SIGNAL(destroyed(QObject *)), globalFactory, SLOT(objectDestroyed(QObject *)), Qt::DirectConnection); + globalFactory->objects.append(o); + } + return o; +} + +} //namespace Phonon + +QT_END_NAMESPACE + +#include "factory.moc" +#include "moc_factory_p.cpp" + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/factory_p.h b/src/3rdparty/phonon/phonon/factory_p.h new file mode 100644 index 0000000..41b8c5b --- /dev/null +++ b/src/3rdparty/phonon/phonon/factory_p.h @@ -0,0 +1,203 @@ +/* This file is part of the KDE project + Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_FACTORY_P_H +#define PHONON_FACTORY_P_H + +#include "phonon_export.h" + +#include <QtCore/QObject> +#include <QtCore/QStringList> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QUrl; +class QIcon; + +namespace Phonon +{ + class PlatformPlugin; + class MediaNodePrivate; + class AbstractMediaStream; + +/** + * \internal + * \brief Factory to access the preferred Backend. + * + * This class is used internally to get the backend's implementation. + * It keeps track of the objects that were created. When a + * request for a backend change comes, it asks all frontend objects to delete + * their backend objects and then checks whether they were all deleted. Only + * then the old backend is unloaded and the new backend is loaded. + * + * \author Matthias Kretz <kretz@kde.org> + */ +namespace Factory +{ + /** + * Emits signals for Phonon::Factory. + */ + class Sender : public QObject + { + Q_OBJECT + Q_SIGNALS: + /** + * Emitted after the backend has successfully been changed. + */ + void backendChanged(); + + /** + * \copydoc BackendCapabilities::Notifier::availableAudioOutputDevicesChanged + */ + void availableAudioOutputDevicesChanged(); + + /** + * \copydoc BackendCapabilities::Notifier::availableAudioCaptureDevicesChanged + */ + void availableAudioCaptureDevicesChanged(); + }; + + /** + * Returns a pointer to the object emitting the signals. + * + * \see Sender::backendChanged() + */ + PHONON_EXPORT Sender *sender(); + + /** + * Create a new backend object for a MediaObject. + * + * \return a pointer to the MediaObject the backend provides. + */ + QObject *createMediaObject(QObject *parent = 0); + /** + * Create a new backend object for a Effect. + * + * \return a pointer to the Effect the backend provides. + */ +#ifndef QT_NO_PHONON_EFFECT + QObject *createEffect(int effectId, QObject *parent = 0); +#endif //QT_NO_PHONON_EFFECT + /** + * Create a new backend object for a VolumeFaderEffect. + * + * \return a pointer to the VolumeFaderEffect the backend provides. + */ +#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + QObject *createVolumeFaderEffect(QObject *parent = 0); +#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + /** + * Create a new backend object for a AudioOutput. + * + * \return a pointer to the AudioOutput the backend provides. + */ + QObject *createAudioOutput(QObject *parent = 0); + /** + * Create a new backend object for a VideoWidget. + * + * \return a pointer to the VideoWidget the backend provides. + */ +#ifndef QT_NO_PHONON_VIDEO + QObject *createVideoWidget(QObject *parent = 0); +#endif //QT_NO_PHONON_VIDEO + + /** + * Create a new backend object for a AudioDataOutput. + * + * \return a pointer to the AudioDataOutput the backend provides. + */ + PHONON_EXPORT QObject *createAudioDataOutput(QObject *parent = 0); + + /** + * \return a pointer to the backend interface. + */ + PHONON_EXPORT QObject *backend(bool createWhenNull = true); + + /** + * Unique identifier for the Backend. Can be used in configuration files + * for example. + */ + QString identifier(); + + /** + * Get the name of the Backend. It's the name from the .desktop file. + */ + PHONON_EXPORT QString backendName(); + + /** + * Get the comment of the Backend. It's the comment from the .desktop file. + */ + QString backendComment(); + + /** + * Get the version of the Backend. It's the version from the .desktop file. + * + * The version is especially interesting if there are several versions + * available for binary incompatible versions of the backend's media + * framework. + */ + QString backendVersion(); + + /** + * Get the icon (name) of the Backend. It's the icon from the .desktop file. + */ + QString backendIcon(); + + /** + * Get the website of the Backend. It's the website from the .desktop file. + */ + QString backendWebsite(); + + /** + * registers the backend object + */ + PHONON_EXPORT QObject *registerQObject(QObject *o); + + bool isMimeTypeAvailable(const QString &mimeType); + + PHONON_EXPORT void registerFrontendObject(MediaNodePrivate *); + PHONON_EXPORT void deregisterFrontendObject(MediaNodePrivate *); + + PHONON_EXPORT void setBackend(QObject *); + //PHONON_EXPORT void createBackend(const QString &library, const QString &version = QString()); + + PHONON_EXPORT PlatformPlugin *platformPlugin(); + +//X It is probably better if we can get away with internal handling of +//X freeing the soundcard device when it's not needed anymore and +//X providing an IPC method to stop all MediaObjects -> free all +//X devices +//X /** +//X * \internal +//X * This is called when the application needs to free the soundcard +//X * device(s). +//X */ +//X void freeSoundcardDevices(); +} // namespace Factory +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_FACTORY_P_H +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/frontendinterface_p.h b/src/3rdparty/phonon/phonon/frontendinterface_p.h new file mode 100644 index 0000000..83ad780 --- /dev/null +++ b/src/3rdparty/phonon/phonon/frontendinterface_p.h @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_FRONTENDINTERFACEPRIVATE_H +#define PHONON_FRONTENDINTERFACEPRIVATE_H + +#include "addoninterface.h" +#include "mediaobject_p.h" +#include "phononnamespace_p.h" +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_MEDIACONTROLLER + +namespace Phonon +{ +class FrontendInterfacePrivate +{ + public: + FrontendInterfacePrivate(MediaObject *mp) : media(mp) { + Q_ASSERT(media); + MediaObjectPrivate *d = media->k_func(); + d->interfaceList << this; + } + virtual ~FrontendInterfacePrivate() { + if (media) { + MediaObjectPrivate *d = media->k_func(); + d->interfaceList << this; + } + } + virtual void backendObjectChanged(QObject *iface) = 0; + void _backendObjectChanged() { + pDebug() << Q_FUNC_INFO; + QObject *x = media->k_ptr->backendObject(); + if (x) { + backendObjectChanged(x); + } + } + AddonInterface *iface() { return qobject_cast<AddonInterface *>(media->k_ptr->backendObject()); } + QPointer<MediaObject> media; +}; +} // namespace Phonon + +#endif //QT_NO_PHONON_MEDIACONTROLLER + +QT_END_NAMESPACE + +#endif // PHONON_FRONTENDINTERFACEPRIVATE_H diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp new file mode 100644 index 0000000..f83ebc4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/globalconfig.cpp @@ -0,0 +1,449 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "globalconfig.h" +#include "globalconfig_p.h" + +#include "factory_p.h" +#include "objectdescription.h" +#include "phonondefs_p.h" +#include "platformplugin.h" +#include "backendinterface.h" +#include "qsettingsgroup_p.h" +#include "phononnamespace_p.h" +#include "pulsesupport.h" + +#include <QtCore/QList> +#include <QtCore/QVariant> + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +GlobalConfigPrivate::GlobalConfigPrivate() : config(QLatin1String("kde.org"), QLatin1String("libphonon")) +{ +} + +GlobalConfig::GlobalConfig() + : k_ptr(new GlobalConfigPrivate) +{ +} + +GlobalConfig::~GlobalConfig() +{ + delete k_ptr; +} + +enum WhatToFilter { + FilterAdvancedDevices = 1, + FilterHardwareDevices = 2, + FilterUnavailableDevices = 4 +}; + +static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter) +{ + QMutableListIterator<int> it(*list); + while (it.hasNext()) { + QHash<QByteArray, QVariant> properties; + if (backendIface) + properties = backendIface->objectDescriptionProperties(type, it.next()); + else + properties = PulseSupport::getInstance()->objectDescriptionProperties(type, it.next()); + QVariant var; + if (whatToFilter & FilterAdvancedDevices) { + var = properties.value("isAdvanced"); + if (var.isValid() && var.toBool()) { + it.remove(); + continue; + } + } + if (whatToFilter & FilterHardwareDevices) { + var = properties.value("isHardwareDevice"); + if (var.isValid() && var.toBool()) { + it.remove(); + continue; +#ifndef QT_NO_PHONON_SETTINGSGROUP + } + } + if (whatToFilter & FilterUnavailableDevices) { + var = properties.value("available"); + if (var.isValid() && !var.toBool()) { + it.remove(); + continue; + } + } + } +} + +static QList<int> sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, Phonon::Category category, QList<int> &defaultList) +{ + Q_ASSERT(config); Q_UNUSED(config); + Q_ASSERT(backendConfig); + Q_ASSERT(type == AudioOutputDeviceType || type == AudioCaptureDeviceType); + + if (defaultList.size() <= 1) { + // nothing to sort + return defaultList; + } else { + // make entries unique + QSet<int> seen; + QMutableListIterator<int> it(defaultList); + while (it.hasNext()) { + if (seen.contains(it.next())) { + it.remove(); + } else { + seen.insert(it.value()); + } + } + } + + QList<int> deviceList; + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + deviceList = pulse->objectIndexesByCategory(type, category); + } else { + QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category)); + if (!backendConfig->hasKey(categoryKey)) { + // no list in config for the given category + categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory)); + if (!backendConfig->hasKey(categoryKey)) { + // no list in config for NoCategory + return defaultList; + } + } + + //Now the list from d->config + deviceList = backendConfig->value(categoryKey, QList<int>()); + } + + //if there are devices in d->config that the backend doesn't report, remove them from the list + QMutableListIterator<int> i(deviceList); + while (i.hasNext()) { + if (0 == defaultList.removeAll(i.next())) { + i.remove(); + } + } + + //if the backend reports more devices that are not in d->config append them to the list + deviceList += defaultList; + + return deviceList; +} + +bool GlobalConfig::hideAdvancedDevices() const +{ + K_D(const GlobalConfig); + //The devices need to be stored independently for every backend + const QSettingsGroup generalGroup(&d->config, QLatin1String("General")); + return generalGroup.value(QLatin1String("HideAdvancedDevices"), true); +} + +void GlobalConfig::setHideAdvancedDevices(bool hide) +{ + K_D(GlobalConfig); + QSettingsGroup generalGroup(&d->config, QLatin1String("General")); + generalGroup.setValue(QLatin1String("HideAdvancedDevices"), hide); +} + +static bool isHiddenAudioOutputDevice(const GlobalConfig *config, int i) +{ + Q_ASSERT(config); + + if (!config->hideAdvancedDevices()) + return false; + + AudioOutputDevice ad = AudioOutputDevice::fromIndex(i); + const QVariant var = ad.property("isAdvanced"); + return (var.isValid() && var.toBool()); +} + +#ifndef QT_NO_PHONON_AUDIOCAPTURE +static bool isHiddenAudioCaptureDevice(const GlobalConfig *config, int i) +{ + Q_ASSERT(config); + + if (!config->hideAdvancedDevices()) + return false; + + AudioCaptureDevice ad = AudioCaptureDevice::fromIndex(i); + const QVariant var = ad.property("isAdvanced"); + return (var.isValid() && var.toBool()); +} +#endif + +static QList<int> reindexList(const GlobalConfig *config, Phonon::Category category, QList<int>newOrder, bool output) +{ + Q_ASSERT(config); +#ifdef QT_NO_PHONON_AUDIOCAPTURE + Q_ASSERT(output); +#endif + + /*QString sb; + sb = QString("(Size %1)").arg(currentList.size()); + foreach (int i, currentList) + sb += QString("%1, ").arg(i); + fprintf(stderr, "=== Reindex Current: %s\n", sb.toUtf8().constData()); + sb = QString("(Size %1)").arg(newOrder.size()); + foreach (int i, newOrder) + sb += QString("%1, ").arg(i); + fprintf(stderr, "=== Reindex Before : %s\n", sb.toUtf8().constData());*/ + + QList<int> currentList; + if (output) + currentList = config->audioOutputDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices); +#ifndef QT_NO_PHONON_AUDIOCAPTURE + else + currentList = config->audioCaptureDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices); +#endif + + QList<int> newList; + + foreach (int i, newOrder) { + int found = currentList.indexOf(i); + if (found < 0) { + // It's not in the list, so something is odd (e.g. client error). Ignore it. + continue; + } + + // Iterate through the list from this point onward. If there are hidden devices + // immediately following, take them too. + newList.append(currentList.takeAt(found)); + while (found < currentList.size()) { + bool hidden = true; + if (output) + hidden = isHiddenAudioOutputDevice(config, currentList.at(found)); +#ifndef QT_NO_PHONON_AUDIOCAPTURE + else + hidden = isHiddenAudioCaptureDevice(config, currentList.at(found)); +#endif + + if (!hidden) + break; + newList.append(currentList.takeAt(found)); + } + } + + // If there are any devices left in.. just tack them on the end. + if (currentList.size() > 0) + newList += currentList; + + /*sb = QString("(Size %1)").arg(newList.size()); + foreach (int i, newList) + sb += QString("%1, ").arg(i); + fprintf(stderr, "=== Reindex After : %s\n", sb.toUtf8().constData());*/ + return newList; +} + + +void GlobalConfig::setAudioOutputDeviceListFor(Phonon::Category category, QList<int> order) +{ + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + pulse->setOutputDevicePriorityForCategory(category, order); + return; + } + + K_D(GlobalConfig); + QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier()); + + order = reindexList(this, category, order, true); + + const QList<int> noCategoryOrder = audioOutputDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices); + if (category != Phonon::NoCategory && order == noCategoryOrder) { + backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category)); + } else { + backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order); + } +} +#endif //QT_NO_PHONON_SETTINGSGROUP + +#ifndef QT_NO_PHONON_SETTINGSGROUP +QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int override) const +{ + K_D(const GlobalConfig); + + const bool hide = ((override & AdvancedDevicesFromSettings) + ? hideAdvancedDevices() + : static_cast<bool>(override & HideAdvancedDevices)); + + QList<int> defaultList; + + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + defaultList = pulse->objectDescriptionIndexes(Phonon::AudioOutputDeviceType); + if (hide || (override & HideUnavailableDevices)) { + filter(AudioOutputDeviceType, NULL, &defaultList, + (hide ? FilterAdvancedDevices : 0) + | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) + ); + } + } else { + BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend()); + +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) { + // the platform plugin lists the audio devices for the platform + // this list already is in default order (as defined by the platform plugin) + defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType); + if (hide) { + QMutableListIterator<int> it(defaultList); + while (it.hasNext()) { + AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next()); + const QVariant var = objDesc.property("isAdvanced"); + if (var.isValid() && var.toBool()) { + it.remove(); + } + } + } + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + + // lookup the available devices directly from the backend + if (backendIface) { + // this list already is in default order (as defined by the backend) + QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType); + if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) { + filter(AudioOutputDeviceType, backendIface, &list, + (hide ? FilterAdvancedDevices : 0) + // the platform plugin maybe already provided the hardware devices? + | (defaultList.isEmpty() ? 0 : FilterHardwareDevices) + | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) + ); + } + defaultList += list; + } + } + + const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier()); + return sortDevicesByCategoryPriority(this, &backendConfig, AudioOutputDeviceType, category, defaultList); +} +#endif //QT_NO_PHONON_SETTINGSGROUP +int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) const +{ +#ifndef QT_NO_PHONON_SETTINGSGROUP + QList<int> ret = audioOutputDeviceListFor(category, override); + if (!ret.isEmpty()) + return ret.first(); +#endif //QT_NO_PHONON_SETTINGSGROUP + return -1; +} + +#ifndef QT_NO_PHONON_AUDIOCAPTURE +void GlobalConfig::setAudioCaptureDeviceListFor(Phonon::Category category, QList<int> order) +{ +#ifndef QT_NO_PHONON_SETTINGSGROUP + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + pulse->setCaptureDevicePriorityForCategory(category, order); + return; + } + + K_D(GlobalConfig); + QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier()); + + order = reindexList(this, category, order, false); + + const QList<int> noCategoryOrder = audioCaptureDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices); + if (category != Phonon::NoCategory && order == noCategoryOrder) { + backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category)); + } else { + backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order); + } +} + +QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, int override) const +{ + K_D(const GlobalConfig); + + const bool hide = ((override & AdvancedDevicesFromSettings) + ? hideAdvancedDevices() + : static_cast<bool>(override & HideAdvancedDevices)); + + QList<int> defaultList; + + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + defaultList = pulse->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType); + if (hide || (override & HideUnavailableDevices)) { + filter(AudioCaptureDeviceType, NULL, &defaultList, + (hide ? FilterAdvancedDevices : 0) + | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) + ); + } + } else { + BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend()); + +#ifndef QT_NO_PHONON_PLATFORMPLUGIN +#else //QT_NO_SETTINGSGROUP + return QList<int>(); +#endif //QT_NO_SETTINGSGROUP + if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) { + // the platform plugin lists the audio devices for the platform + // this list already is in default order (as defined by the platform plugin) + defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType); + if (hide) { + QMutableListIterator<int> it(defaultList); + while (it.hasNext()) { + AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next()); + const QVariant var = objDesc.property("isAdvanced"); + if (var.isValid() && var.toBool()) { + it.remove(); + } + } + } + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + + // lookup the available devices directly from the backend + if (backendIface) { + // this list already is in default order (as defined by the backend) + QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType); + if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) { + filter(AudioCaptureDeviceType, backendIface, &list, + (hide ? FilterAdvancedDevices : 0) + // the platform plugin maybe already provided the hardware devices? + | (defaultList.isEmpty() ? 0 : FilterHardwareDevices) + | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) + ); + } + defaultList += list; + } + } + + const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier()); + return sortDevicesByCategoryPriority(this, &backendConfig, AudioCaptureDeviceType, category, defaultList); +} + +int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category, int override) const +{ + QList<int> ret = audioCaptureDeviceListFor(category, override); + if (ret.isEmpty()) + return -1; + return ret.first(); +} +#endif //QT_NO_PHONON_AUDIOCAPTURE + + +} // namespace Phonon + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/globalconfig.h b/src/3rdparty/phonon/phonon/globalconfig.h new file mode 100644 index 0000000..5233c7b --- /dev/null +++ b/src/3rdparty/phonon/phonon/globalconfig.h @@ -0,0 +1,71 @@ +/* This file is part of the KDE project +Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_GLOBALCONFIG_H +#define PHONON_GLOBALCONFIG_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include "phonondefs.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class GlobalConfigPrivate; + + class PHONON_EXPORT GlobalConfig + { + K_DECLARE_PRIVATE(GlobalConfig) + public: + GlobalConfig(); + virtual ~GlobalConfig(); + + enum DevicesToHideFlag { + ShowUnavailableDevices = 0, + ShowAdvancedDevices = 0, + HideAdvancedDevices = 1, + AdvancedDevicesFromSettings = 2, + HideUnavailableDevices = 4 + }; + bool hideAdvancedDevices() const; + void setHideAdvancedDevices(bool hide = true); + void setAudioOutputDeviceListFor(Phonon::Category category, QList<int> order); + QList<int> audioOutputDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + int audioOutputDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + +#ifndef QT_NO_PHONON_AUDIOCAPTURE + void setAudioCaptureDeviceListFor(Phonon::Category category, QList<int> order); + QList<int> audioCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + int audioCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; +#endif //QT_NO_PHONON_AUDIOCAPTURE + + protected: + GlobalConfigPrivate *const k_ptr; + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_GLOBALCONFIG_H diff --git a/src/3rdparty/phonon/phonon/globalconfig_p.h b/src/3rdparty/phonon/phonon/globalconfig_p.h new file mode 100644 index 0000000..090ca6b --- /dev/null +++ b/src/3rdparty/phonon/phonon/globalconfig_p.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE project +Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_GLOBALCONFIG_P_H +#define PHONON_GLOBALCONFIG_P_H + +#include <QtCore/QSettings> + +#include "phonon_export.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class GlobalConfigPrivate + { + public: + GlobalConfigPrivate(); + virtual ~GlobalConfigPrivate() {} + + QSettings config; + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_GLOBALCONFIG_P_H diff --git a/src/3rdparty/phonon/phonon/globalstatic_p.h b/src/3rdparty/phonon/phonon/globalstatic_p.h new file mode 100644 index 0000000..cf80512 --- /dev/null +++ b/src/3rdparty/phonon/phonon/globalstatic_p.h @@ -0,0 +1,293 @@ +/* This file is part of the KDE libraries + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PHONON_GLOBALSTATIC_P_H +#define PHONON_GLOBALSTATIC_P_H + +#include <QtCore/QAtomicPointer> + +// +// WARNING!! +// This code uses undocumented Qt API +// Do not copy it to your application! Use only the functions that are here! +// Otherwise, it could break when a new version of Qt ships. +// + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +/** + * @internal + */ +typedef void (*CleanUpFunction)(); + +/** + * @internal + * + * Helper class for PHONON_GLOBAL_STATIC to clean up the object on library unload or application + * shutdown. + */ +class CleanUpGlobalStatic +{ + public: + CleanUpFunction func; + + inline ~CleanUpGlobalStatic() { func(); } +}; + +} // namespace Phonon + +#ifdef Q_CC_MSVC +/** + * @internal + * + * MSVC seems to give anonymous structs the same name which fails at link time. So instead we name + * the struct and hope that by adding the line number to the name it's unique enough to never clash. + */ +# define PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) _k_##NAME##__LINE__ +#else +/** + * @internal + * + * Make the struct of the PHONON_GLOBAL_STATIC anonymous. + */ +# define PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) +#endif + +/** + * This macro makes it easy to use non-POD types as global statics. + * The object is created on first use and creation is threadsafe. + * + * The object is destructed on library unload or application exit. + * Be careful with calling other objects in the destructor of the class + * as you have to be sure that they (or objects they depend on) are not already destructed. + * + * @param TYPE The type of the global static object. Do not add a *. + * @param NAME The name of the function to get a pointer to the global static object. + * + * If you have code that might be called after the global object has been destroyed you can check + * for that using the isDestroyed() function. + * + * If needed (If the destructor of the global object calls other functions that depend on other + * global statics (e.g. KConfig::sync) your destructor has to be called before those global statics + * are destroyed. A Qt post routine does that.) you can also install a post routine (@ref qAddPostRoutine) to clean up the object + * using the destroy() method. If you registered a post routine and the object is destroyed because + * of a lib unload you have to call qRemovePostRoutine! + * + * Example: + * @code + * class A { + * public: + * ~A(); + * ... + * }; + * + * PHONON_GLOBAL_STATIC(A, globalA) + * // The above creates a new globally static variable named 'globalA' which you + * // can use as a pointer to an instance of A. + * + * void doSomething() + * { + * // The first time you access globalA a new instance of A will be created automatically. + * A *a = globalA; + * ... + * } + * + * void doSomethingElse() + * { + * if (globalA.isDestroyed()) { + * return; + * } + * A *a = globalA; + * ... + * } + * + * void installPostRoutine() + * { + * // A post routine can be used to delete the object when QCoreApplication destructs, + * // not adding such a post routine will delete the object normally at program unload + * qAddPostRoutine(globalA.destroy); + * } + * + * A::~A() + * { + * // When you install a post routine you have to remove the post routine from the destructor of + * // the class used as global static! + * qRemovePostRoutine(globalA.destroy); + * } + * @endcode + * + * A common case for the need of deletion on lib unload/app shutdown are Singleton classes. Here's + * an example how to do it: + * @code + * class MySingletonPrivate; + * class EXPORT_MACRO MySingleton + * { + * friend class MySingletonPrivate; + * public: + * static MySingleton *self(); + * QString someFunction(); + * + * private: + * MySingleton(); + * ~MySingleton(); + * }; + * @endcode + * in the .cpp file: + * @code + * // This class will be instantiated and referenced as a singleton in this example + * class MySingletonPrivate + * { + * public: + * QString foo; + * MySingleton instance; + * }; + * + * PHONON_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate) + * + * MySingleton *MySingleton::self() + * { + * // returns the singleton; automatically creates a new instance if that has not happened yet. + * return &mySingletonPrivate->instance; + * } + * QString MySingleton::someFunction() + * { + * // Refencing the singleton directly is possible for your convenience + * return mySingletonPrivate->foo; + * } + * @endcode + * + * Instead of the above you can use also the following pattern (ignore the name of the namespace): + * @code + * namespace MySingleton + * { + * EXPORT_MACRO QString someFunction(); + * } + * @endcode + * in the .cpp file: + * @code + * class MySingletonPrivate + * { + * public: + * QString foo; + * }; + * + * PHONON_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate) + * + * QString MySingleton::someFunction() + * { + * return mySingletonPrivate->foo; + * } + * @endcode + * + * Now code that wants to call someFunction() doesn't have to do + * @code + * MySingleton::self()->someFunction(); + * @endcode + * anymore but instead: + * @code + * MySingleton::someFunction(); + * @endcode + * + * @ingroup KDEMacros + */ +#define PHONON_GLOBAL_STATIC(TYPE, NAME) PHONON_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ()) + +/** + * @overload + * This is the same as PHONON_GLOBAL_STATIC, but can take arguments that are passed + * to the object's constructor + * + * @param TYPE The type of the global static object. Do not add a *. + * @param NAME The name of the function to get a pointer to the global static object. + * @param ARGS the list of arguments, between brackets + * + * Example: + * @code + * class A + * { + * public: + * A(const char *s, int i); + * ... + * }; + * + * PHONON_GLOBAL_STATIC_WITH_ARG(A, globalA, ("foo", 0)) + * // The above creates a new globally static variable named 'globalA' which you + * // can use as a pointer to an instance of A. + * + * void doSomething() + * { + * // The first time you access globalA a new instance of A will be created automatically. + * A *a = globalA; + * ... + * } + * @endcode + * + * @ingroup KDEMacros + */ +#define PHONON_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \ +static QBasicAtomicPointer<TYPE > _k_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(0); \ +static bool _k_static_##NAME##_destroyed; \ +static struct PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) \ +{ \ + bool isDestroyed() \ + { \ + return _k_static_##NAME##_destroyed; \ + } \ + inline operator TYPE*() \ + { \ + return operator->(); \ + } \ + inline TYPE *operator->() \ + { \ + TYPE *p = _k_static_##NAME; \ + if (!p) { \ + if (isDestroyed()) { \ + qFatal("Fatal Error: Accessed global static '%s *%s()' after destruction. " \ + "Defined at %s:%d", #TYPE, #NAME, __FILE__, __LINE__); \ + } \ + p = new TYPE ARGS; \ + if (!_k_static_##NAME.testAndSetOrdered(0, p)) { \ + delete p; \ + p = _k_static_##NAME; \ + } else { \ + static Phonon::CleanUpGlobalStatic cleanUpObject = { destroy }; \ + } \ + } \ + return p; \ + } \ + inline TYPE &operator*() \ + { \ + return *operator->(); \ + } \ + static void destroy() \ + { \ + _k_static_##NAME##_destroyed = true; \ + TYPE *x = _k_static_##NAME; \ + _k_static_##NAME = 0; \ + delete x; \ + } \ +} NAME; + +QT_END_NAMESPACE +#endif // PHONON_GLOBALSTATIC_P_H diff --git a/src/3rdparty/phonon/phonon/iodevicestream.cpp b/src/3rdparty/phonon/phonon/iodevicestream.cpp new file mode 100644 index 0000000..3735f75 --- /dev/null +++ b/src/3rdparty/phonon/phonon/iodevicestream.cpp @@ -0,0 +1,100 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "iodevicestream_p.h" +#include "abstractmediastream_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +namespace Phonon +{ + +class IODeviceStreamPrivate : public AbstractMediaStreamPrivate +{ + Q_DECLARE_PUBLIC(IODeviceStream) + protected: + IODeviceStreamPrivate(QIODevice *_ioDevice) + : ioDevice(_ioDevice) + { + if (!ioDevice->isOpen()) { + ioDevice->open(QIODevice::ReadOnly); + } + Q_ASSERT(ioDevice->isOpen()); + Q_ASSERT(ioDevice->isReadable()); + streamSize = ioDevice->size(); + streamSeekable = !ioDevice->isSequential(); + } + + private: + QIODevice *ioDevice; +}; + +IODeviceStream::IODeviceStream(QIODevice *ioDevice, QObject *parent) + : AbstractMediaStream(*new IODeviceStreamPrivate(ioDevice), parent) +{ + Q_D(IODeviceStream); + d->ioDevice->reset(); +} + +IODeviceStream::~IODeviceStream() +{ +} + +void IODeviceStream::reset() +{ + Q_D(IODeviceStream); + d->ioDevice->reset(); + //resetDone(); +} + +void IODeviceStream::needData() +{ + quint32 size = 4096; + Q_D(IODeviceStream); + const QByteArray data = d->ioDevice->read(size); + if (data.isEmpty() && !d->ioDevice->atEnd()) { + error(Phonon::NormalError, d->ioDevice->errorString()); + } + writeData(data); + if (d->ioDevice->atEnd()) { + endOfData(); + } +} + +void IODeviceStream::seekStream(qint64 offset) +{ + Q_D(IODeviceStream); + d->ioDevice->seek(offset); + //seekStreamDone(); +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE + +#include "moc_iodevicestream_p.cpp" + +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/iodevicestream_p.h b/src/3rdparty/phonon/phonon/iodevicestream_p.h new file mode 100644 index 0000000..cca77e3 --- /dev/null +++ b/src/3rdparty/phonon/phonon/iodevicestream_p.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_IODEVICESTREAM_P_H +#define PHONON_IODEVICESTREAM_P_H + +#include "abstractmediastream.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +class QIODevice; + +namespace Phonon +{ + +class IODeviceStreamPrivate; +class IODeviceStream : public AbstractMediaStream +{ + Q_OBJECT + Q_DECLARE_PRIVATE(IODeviceStream) + public: + explicit IODeviceStream(QIODevice *ioDevice, QObject *parent = 0); + ~IODeviceStream(); + + void reset(); + void needData(); + void seekStream(qint64); +}; +} // namespace Phonon + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_IODEVICESTREAM_P_H diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp new file mode 100644 index 0000000..3dc22b7 --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp @@ -0,0 +1,239 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + Copyright (C) 2008 Ian Monroe <ian@monroe.nu> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "mediacontroller.h" +#include "mediaobject.h" +#include "addoninterface.h" +#include <QtCore/QList> +#include <QtCore/QVariant> +#include "frontendinterface_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_MEDIACONTROLLER + +namespace Phonon +{ + +class MediaControllerPrivate : public FrontendInterfacePrivate +{ + public: + MediaControllerPrivate(MediaObject *mp) : FrontendInterfacePrivate(mp) {} + + virtual void backendObjectChanged(QObject *); + MediaController *q; +}; + +MediaController::MediaController(MediaObject *mp) + : QObject(mp) + , d(new MediaControllerPrivate(mp)) +{ + d->q = this; + d->_backendObjectChanged(); +} + +void MediaControllerPrivate::backendObjectChanged(QObject *m_backendObject) +{ + QObject::connect(m_backendObject, SIGNAL(availableSubtitlesChanged()), q, SIGNAL(availableSubtitlesChanged())); + QObject::connect(m_backendObject, SIGNAL(availableAudioChannelsChanged()), q, SIGNAL(availableAudioChannelsChanged())); + QObject::connect(m_backendObject, SIGNAL(titleChanged(int)), q, SIGNAL(titleChanged(int))); + QObject::connect(m_backendObject, SIGNAL(availableTitlesChanged(int)), q, SIGNAL(availableTitlesChanged(int))); + QObject::connect(m_backendObject, SIGNAL(chapterChanged(int)), q, SIGNAL(chapterChanged(int))); + QObject::connect(m_backendObject, SIGNAL(availableChaptersChanged(int)), q, SIGNAL(availableChaptersChanged(int))); + QObject::connect(m_backendObject, SIGNAL(angleChanged(int)), q, SIGNAL(angleChanged(int))); + QObject::connect(m_backendObject, SIGNAL(availableAnglesChanged(int)), q, SIGNAL(availableAnglesChanged(int))); +} + +MediaController::~MediaController() +{ + delete d; +} + +#define IFACE \ + AddonInterface *iface = d->iface(); \ + if (!iface) return + +MediaController::Features MediaController::supportedFeatures() const +{ + if (!d || !d->media) { + return Features(); + } + IFACE Features(); + Features ret; + if (iface->hasInterface(AddonInterface::AngleInterface)) { + ret |= Angles; + } + if (iface->hasInterface(AddonInterface::ChapterInterface)) { + ret |= Chapters; + } + if (iface->hasInterface(AddonInterface::TitleInterface)) { + ret |= Titles; + } + return ret; +} + +int MediaController::availableTitles() const +{ + IFACE 0; + return iface->interfaceCall(AddonInterface::TitleInterface, + AddonInterface::availableTitles).toInt(); +} + +int MediaController::currentTitle() const +{ + IFACE 0; + return iface->interfaceCall(AddonInterface::TitleInterface, + AddonInterface::title).toInt(); +} + +void MediaController::setCurrentTitle(int titleNumber) +{ + IFACE; + iface->interfaceCall(AddonInterface::TitleInterface, + AddonInterface::setTitle, QList<QVariant>() << QVariant(titleNumber)); +} + +bool MediaController::autoplayTitles() const +{ + IFACE true; + return iface->interfaceCall(AddonInterface::TitleInterface, + AddonInterface::autoplayTitles).toBool(); +} + +void MediaController::setAutoplayTitles(bool b) +{ + IFACE; + iface->interfaceCall(AddonInterface::TitleInterface, + AddonInterface::setAutoplayTitles, QList<QVariant>() << QVariant(b)); +} + +void MediaController::nextTitle() +{ + setCurrentTitle(currentTitle() + 1); +} + +void MediaController::previousTitle() +{ + setCurrentTitle(currentTitle() - 1); +} + +int MediaController::availableChapters() const +{ + IFACE 0; + return iface->interfaceCall(AddonInterface::ChapterInterface, + AddonInterface::availableChapters).toInt(); +} + +int MediaController::currentChapter() const +{ + IFACE 0; + return iface->interfaceCall(AddonInterface::ChapterInterface, + AddonInterface::chapter).toInt(); +} + +void MediaController::setCurrentChapter(int titleNumber) +{ + IFACE; + iface->interfaceCall(AddonInterface::ChapterInterface, + AddonInterface::setChapter, QList<QVariant>() << QVariant(titleNumber)); +} + +int MediaController::availableAngles() const +{ + IFACE 0; + return iface->interfaceCall(AddonInterface::AngleInterface, + AddonInterface::availableAngles).toInt(); +} + +int MediaController::currentAngle() const +{ + IFACE 0; + return iface->interfaceCall(AddonInterface::AngleInterface, + AddonInterface::angle).toInt(); +} + +void MediaController::setCurrentAngle(int titleNumber) +{ + IFACE; + iface->interfaceCall(AddonInterface::AngleInterface, + AddonInterface::setAngle, QList<QVariant>() << QVariant(titleNumber)); +} + +AudioChannelDescription MediaController::currentAudioChannel() const +{ + IFACE AudioChannelDescription(); + return iface->interfaceCall(AddonInterface::AudioChannelInterface, + AddonInterface::currentAudioChannel).value<AudioChannelDescription>(); +} + +SubtitleDescription MediaController::currentSubtitle() const +{ + IFACE SubtitleDescription(); + return iface->interfaceCall(AddonInterface::SubtitleInterface, + AddonInterface::currentSubtitle).value<SubtitleDescription>(); +} + +QList<AudioChannelDescription> MediaController::availableAudioChannels() const +{ + QList<AudioChannelDescription> retList; + IFACE retList; + retList = iface->interfaceCall(AddonInterface::AudioChannelInterface, + AddonInterface::availableAudioChannels).value< QList<AudioChannelDescription> >(); + return retList; +} + +QList<SubtitleDescription> MediaController::availableSubtitles() const +{ + QList<SubtitleDescription> retList; + IFACE retList; + retList = iface->interfaceCall(AddonInterface::SubtitleInterface, + AddonInterface::availableSubtitles) + .value< QList<SubtitleDescription> >(); + return retList; +} + +void MediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescription &stream) +{ + IFACE; + iface->interfaceCall(AddonInterface::AudioChannelInterface, + AddonInterface::setCurrentAudioChannel, QList<QVariant>() << QVariant::fromValue(stream)); +} + +void MediaController::setCurrentSubtitle(const Phonon::SubtitleDescription &stream) +{ + IFACE; + iface->interfaceCall(AddonInterface::SubtitleInterface, + AddonInterface::setCurrentSubtitle, QList<QVariant>() << QVariant::fromValue(stream)); +} + +#undef IFACE + +} // namespace Phonon + +#endif //QT_NO_PHONON_MEDIACONTROLLER + +QT_END_NAMESPACE + +#include "moc_mediacontroller.cpp" + +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/mediacontroller.h b/src/3rdparty/phonon/phonon/mediacontroller.h new file mode 100644 index 0000000..109a79e --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediacontroller.h @@ -0,0 +1,188 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_MEDIACONTROLLER_H +#define PHONON_MEDIACONTROLLER_H + +#include "phonon_export.h" +#include "objectdescription.h" + +#include <QtCore/QObject> +#include <QtCore/QtGlobal> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_MEDIACONTROLLER + +namespace Phonon +{ +class MediaControllerPrivate; +class MediaObject; + +/** \class MediaController mediacontroller.h Phonon/MediaController + * \brief Controls optional features of a media file/device like title, chapter, angle. + * + * \ingroup Playback + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT MediaController : public QObject +{ + Q_OBJECT + Q_FLAGS(Features) + public: + enum Feature { + Angles = 1, + Chapters = 2, + Titles = 4 + }; + Q_DECLARE_FLAGS(Features, Feature) + + MediaController(MediaObject *parent); + ~MediaController(); + + Features supportedFeatures() const; + + int availableAngles() const; + int currentAngle() const; + + int availableChapters() const; + int currentChapter() const; + + int availableTitles() const; + int currentTitle() const; + + bool autoplayTitles() const; + + /** + * Returns the selected audio stream. + * + * \see availableAudioChannels + * \see setCurrentAudioChannel + */ + AudioChannelDescription currentAudioChannel() const; + + /** + * Returns the selected subtitle stream. + * + * \see availableSubtitles + * \see setCurrentSubtitle + */ + SubtitleDescription currentSubtitle() const; + + /** + * Returns the audio streams that can be selected by the user. The + * strings can directly be used in the user interface. + * + * \see selectedAudioChannel + * \see setCurrentAudioChannel + */ + QList<AudioChannelDescription> availableAudioChannels() const; + + /** + * Returns the subtitle streams that can be selected by the user. The + * strings can directly be used in the user interface. + * + * \see selectedSubtitle + * \see setCurrentSubtitle + */ + QList<SubtitleDescription> availableSubtitles() const; + + /** + * Selects an audio stream from the media. + * + * Some media formats allow multiple audio streams to be stored in + * the same file. Normally only one should be played back. + * + * \param stream Description of an audio stream + * + * \see availableAudioChannels() + * \see currentAudioChannel() + */ + void setCurrentAudioChannel(const Phonon::AudioChannelDescription &stream); + + /** + * Selects a subtitle stream from the media. + * + * Some media formats allow multiple subtitle streams to be stored in + * the same file. Normally only one should be displayed. + * + * \param stream description of a subtitle stream + * + * \see availableSubtitles() + * \see currentSubtitle() + */ + void setCurrentSubtitle(const Phonon::SubtitleDescription &stream); + + public Q_SLOTS: + void setCurrentAngle(int angleNumber); + void setCurrentChapter(int chapterNumber); + + /** + * Skips to the given title \p titleNumber. + * + * If it was playing before the title change it will start playback on the new title if + * autoplayTitles is enabled. + */ + void setCurrentTitle(int titleNumber); + void setAutoplayTitles(bool); + + /** + * Skips to the next title. + * + * If it was playing before the title change it will start playback on the next title if + * autoplayTitles is enabled. + */ + void nextTitle(); + + /** + * Skips to the previous title. + * + * If it was playing before the title change it will start playback on the previous title if + * autoplayTitles is enabled. + */ + void previousTitle(); + + Q_SIGNALS: + void availableSubtitlesChanged(); + void availableAudioChannelsChanged(); + void availableAnglesChanged(int availableAngles); + void angleChanged(int angleNumber); + void availableChaptersChanged(int availableChapters); + void chapterChanged(int chapterNumber); + void availableTitlesChanged(int availableTitles); + void titleChanged(int titleNumber); + + protected: + MediaControllerPrivate *const d; +}; + +} // namespace Phonon + +Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::MediaController::Features) + +#endif //QT_NO_PHONON_MEDIACONTROLLER + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_MEDIACONTROLLER_H diff --git a/src/3rdparty/phonon/phonon/medianode.cpp b/src/3rdparty/phonon/phonon/medianode.cpp new file mode 100644 index 0000000..bc1caed --- /dev/null +++ b/src/3rdparty/phonon/phonon/medianode.cpp @@ -0,0 +1,130 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "medianode.h" +#include "medianode_p.h" +#include "medianodedestructionhandler_p.h" +#include "factory_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + + MediaNode::MediaNode(MediaNodePrivate &dd) + : k_ptr(&dd) + { + k_ptr->q_ptr = this; + } + +bool MediaNode::isValid() const +{ + return const_cast<MediaNodePrivate *>(k_ptr)->backendObject() != 0; +} + + QList<Path> MediaNode::inputPaths() const + { + return k_ptr->inputPaths; + } + + QList<Path> MediaNode::outputPaths() const + { + return k_ptr->outputPaths; + } + + MediaNode::~MediaNode() + { + delete k_ptr; + } + + QObject *MediaNodePrivate::backendObject() + { + if (!m_backendObject && Factory::backend()) { + createBackendObject(); + } + return m_backendObject; + } + + MediaNodePrivate::~MediaNodePrivate() + { + for (int i = 0 ; i < handlers.count(); ++i) { + handlers.at(i)->phononObjectDestroyed(this); + } + Factory::deregisterFrontendObject(this); + delete m_backendObject; + m_backendObject = 0; + } + +void MediaNodePrivate::deleteBackendObject() +{ + if (m_backendObject && aboutToDeleteBackendObject()) { + delete m_backendObject; + m_backendObject = 0; + } +} + + MediaNodePrivate::MediaNodePrivate(MediaNodePrivate::CastId _castId) : castId(_castId), + m_backendObject(0) + { + Factory::registerFrontendObject(this); + } + + void MediaNodePrivate::addDestructionHandler(MediaNodeDestructionHandler *handler) + { + handlers.append(handler); + } + + void MediaNodePrivate::removeDestructionHandler(MediaNodeDestructionHandler *handler) + { + handlers.removeAll(handler); + } + + void MediaNodePrivate::addOutputPath(const Path &p) + { + outputPaths.append(p); + } + + void MediaNodePrivate::addInputPath(const Path &p) + { + inputPaths.append(p); + } + + void MediaNodePrivate::removeOutputPath(const Path &p) + { + int ret = outputPaths.removeAll(p); + Q_ASSERT(ret == 1); + Q_UNUSED(ret); + } + + void MediaNodePrivate::removeInputPath(const Path &p) + { + int ret = inputPaths.removeAll(p); + Q_ASSERT(ret == 1); + Q_UNUSED(ret); + } + + + +} // namespace Phonon + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/medianode.h b/src/3rdparty/phonon/phonon/medianode.h new file mode 100644 index 0000000..6aab189 --- /dev/null +++ b/src/3rdparty/phonon/phonon/medianode.h @@ -0,0 +1,69 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_MEDIANODE_H +#define PHONON_MEDIANODE_H + +#include "phonondefs.h" +#include "phonon_export.h" +#include "path.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + + class Path; + class MediaNodePrivate; + class PHONON_EXPORT MediaNode + { + friend class Path; + friend class PathPrivate; + friend PHONON_EXPORT Path createPath(MediaNode *source, MediaNode *sink); + K_DECLARE_PRIVATE(MediaNode) + public: + virtual ~MediaNode(); + /** + * Tells whether the backend provides an implementation of this + * class. + * + * \return \c true if backend provides an implementation + * \return \c false if the object is not implemented by the backend + */ + bool isValid() const; + + QList<Path> inputPaths() const; + QList<Path> outputPaths() const; + + protected: + MediaNode(MediaNodePrivate &dd); + MediaNodePrivate *const k_ptr; + }; + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_MEDIANODE_H diff --git a/src/3rdparty/phonon/phonon/medianode_p.h b/src/3rdparty/phonon/phonon/medianode_p.h new file mode 100644 index 0000000..e2329a9 --- /dev/null +++ b/src/3rdparty/phonon/phonon/medianode_p.h @@ -0,0 +1,145 @@ +/* This file is part of the KDE project +Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_MEDIANODE_P_H +#define PHONON_MEDIANODE_P_H + +#include <QtCore/QtGlobal> +#include <QtCore/QList> +#include <QtCore/QObject> +#include "path.h" +#include "phonon_export.h" + +QT_BEGIN_NAMESPACE + +class QObject; + +namespace Phonon +{ + class MediaNode; + class MediaNodeDestructionHandler; + + class PHONON_EXPORT MediaNodePrivate + { + Q_DECLARE_PUBLIC(MediaNode) + + friend class AudioOutputPrivate; + friend class FactoryPrivate; + + protected: + enum CastId { + MediaNodePrivateType, + AbstractAudioOutputPrivateType, + AudioOutputType + }; + public: + /** + * Returns the backend object. If the object does not exist it tries to + * create it before returning. + * + * \return the Iface object, might return \c 0 + */ + QObject *backendObject(); + + const CastId castId; + + protected: + MediaNodePrivate(CastId _castId = MediaNodePrivateType); + + virtual ~MediaNodePrivate(); + + /** + * \internal + * This method cleanly deletes the Iface object. It is called on + * destruction and before a backend change. + */ + void deleteBackendObject(); + + virtual bool aboutToDeleteBackendObject() = 0; + + /** + * \internal + * Creates the Iface object belonging to this class. For most cases the + * implementation is + * \code + * Q_Q(ClassName); + * m_iface = Factory::createClassName(this); + * return m_iface; + * \endcode + * + * This function should not be called except from slotCreateIface. + * + * \see slotCreateIface + */ + virtual void createBackendObject() = 0; + + public: + /** + * \internal + * This class has its own destroyed signal since some cleanup calls + * need the pointer to the backend object intact. The + * QObject::destroyed signals comes after the backend object was + * deleted. + * + * As this class cannot derive from QObject a simple handler + * interface is used. + */ + void addDestructionHandler(MediaNodeDestructionHandler *handler); + + /** + * \internal + * This class has its own destroyed signal since some cleanup calls + * need the pointer to the backend object intact. The + * QObject::destroyed signals comes after the backend object was + * deleted. + * + * As this class cannot derive from QObject a simple handler + * interface is used. + */ + void removeDestructionHandler(MediaNodeDestructionHandler *handler); + + void addOutputPath(const Path &); + void addInputPath(const Path &); + void removeOutputPath(const Path &); + void removeInputPath(const Path &); + + const QObject *qObject() const { return const_cast<MediaNodePrivate *>(this)->qObject(); } + virtual QObject *qObject() { return 0; } + + protected: + MediaNode *q_ptr; + public: + QObject *m_backendObject; + protected: + QList<Path> outputPaths; + QList<Path> inputPaths; + + private: + QList<MediaNodeDestructionHandler *> handlers; + Q_DISABLE_COPY(MediaNodePrivate) + }; + +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // PHONON_MEDIANODE_P_H diff --git a/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h b/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h new file mode 100644 index 0000000..9c893f4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef MEDIANODEDESTRUCTIONHANDLER_P_H +#define MEDIANODEDESTRUCTIONHANDLER_P_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +/** + * \internal + * + * Callback interface to keep track of Phonon frontend object destruction. + * + * \author Matthias Kretz <kretz@kde.org> + */ + +class MediaNodePrivate; + +class MediaNodeDestructionHandler +{ + friend class MediaNodePrivate; + +public: + virtual ~MediaNodeDestructionHandler() {} +protected: + /** + * \internal + * called from Base::~Base if this object was registered + * using BasePrivate::addDestructionHandler(). + */ + virtual void phononObjectDestroyed(MediaNodePrivate *) = 0; +}; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // MEDIANODEDESTRUCTIONHANDLER_P_H diff --git a/src/3rdparty/phonon/phonon/mediaobject.cpp b/src/3rdparty/phonon/phonon/mediaobject.cpp new file mode 100644 index 0000000..13d303c --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediaobject.cpp @@ -0,0 +1,572 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "mediaobject.h" +#include "mediaobject_p.h" + +#include "factory_p.h" +#include "mediaobjectinterface.h" +#include "audiooutput.h" +#include "phonondefs_p.h" +#include "abstractmediastream.h" +#include "abstractmediastream_p.h" +#include "frontendinterface_p.h" + +#include <QtCore/QStringList> +#include <QtCore/QUrl> +#include <QtCore/QTimer> + +#include "phononnamespace_p.h" +#include "platform_p.h" + +#define PHONON_CLASSNAME MediaObject +#define PHONON_INTERFACENAME MediaObjectInterface + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +PHONON_OBJECT_IMPL + +MediaObject::~MediaObject() +{ + K_D(MediaObject); + if (d->m_backendObject) { + switch (state()) { + case PlayingState: + case BufferingState: + case PausedState: + stop(); + break; + case ErrorState: + case StoppedState: + case LoadingState: + break; + } + } +} + +Phonon::State MediaObject::state() const +{ + K_D(const MediaObject); +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (d->errorOverride) { + return d->state; + } + if (d->ignoreLoadingToBufferingStateChange) { + return BufferingState; + } + if (d->ignoreErrorToLoadingStateChange) { + return LoadingState; + } +#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (!d->m_backendObject) { + return d->state; + } + return INTERFACE_CALL(state()); +} + +PHONON_INTERFACE_SETTER(setTickInterval, tickInterval, qint32) +PHONON_INTERFACE_GETTER(qint32, tickInterval, d->tickInterval) +PHONON_INTERFACE_GETTER(bool, hasVideo, false) +PHONON_INTERFACE_GETTER(bool, isSeekable, false) +PHONON_INTERFACE_GETTER(qint64, currentTime, d->currentTime) + +static inline bool isPlayable(const MediaSource::Type t) +{ + return t != MediaSource::Invalid && t != MediaSource::Empty; +} + +void MediaObject::play() +{ + K_D(MediaObject); + if (d->backendObject() && isPlayable(d->mediaSource.type())) { + INTERFACE_CALL(play()); + } +} + +void MediaObject::pause() +{ + K_D(MediaObject); + if (d->backendObject() && isPlayable(d->mediaSource.type())) { + INTERFACE_CALL(pause()); + } +} + +void MediaObject::stop() +{ + K_D(MediaObject); + if (d->backendObject() && isPlayable(d->mediaSource.type())) { + INTERFACE_CALL(stop()); + } +} + +void MediaObject::seek(qint64 time) +{ + K_D(MediaObject); + if (d->backendObject() && isPlayable(d->mediaSource.type())) { + INTERFACE_CALL(seek(time)); + } +} + +QString MediaObject::errorString() const +{ + if (state() == Phonon::ErrorState) { + K_D(const MediaObject); +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (d->errorOverride) { + return d->errorString; + } +#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM + return INTERFACE_CALL(errorString()); + } + return QString(); +} + +ErrorType MediaObject::errorType() const +{ + if (state() == Phonon::ErrorState) { + K_D(const MediaObject); +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (d->errorOverride) { + return d->errorType; + } +#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM + return INTERFACE_CALL(errorType()); + } + return Phonon::NoError; +} + +QStringList MediaObject::metaData(Phonon::MetaData f) const +{ + switch (f) { + case ArtistMetaData: + return metaData(QLatin1String("ARTIST" )); + case AlbumMetaData: + return metaData(QLatin1String("ALBUM" )); + case TitleMetaData: + return metaData(QLatin1String("TITLE" )); + case DateMetaData: + return metaData(QLatin1String("DATE" )); + case GenreMetaData: + return metaData(QLatin1String("GENRE" )); + case TracknumberMetaData: + return metaData(QLatin1String("TRACKNUMBER")); + case DescriptionMetaData: + return metaData(QLatin1String("DESCRIPTION")); + case MusicBrainzDiscIdMetaData: + return metaData(QLatin1String("MUSICBRAINZ_DISCID")); + } + return QStringList(); +} + +QStringList MediaObject::metaData(const QString &key) const +{ + K_D(const MediaObject); + return d->metaData.values(key); +} + +QMultiMap<QString, QString> MediaObject::metaData() const +{ + K_D(const MediaObject); + return d->metaData; +} + +PHONON_INTERFACE_GETTER(qint32, prefinishMark, d->prefinishMark) +PHONON_INTERFACE_SETTER(setPrefinishMark, prefinishMark, qint32) + +PHONON_INTERFACE_GETTER(qint32, transitionTime, d->transitionTime) +PHONON_INTERFACE_SETTER(setTransitionTime, transitionTime, qint32) + +qint64 MediaObject::totalTime() const +{ + K_D(const MediaObject); + if (!d->m_backendObject) { + return -1; + } + return INTERFACE_CALL(totalTime()); +} + +qint64 MediaObject::remainingTime() const +{ + K_D(const MediaObject); + if (!d->m_backendObject) { + return -1; + } + qint64 ret = INTERFACE_CALL(remainingTime()); + if (ret < 0) { + return -1; + } + return ret; +} + +MediaSource MediaObject::currentSource() const +{ + K_D(const MediaObject); + return d->mediaSource; +} + +void MediaObject::setCurrentSource(const MediaSource &newSource) +{ + K_D(MediaObject); + if (!k_ptr->backendObject()) { + d->mediaSource = newSource; + return; + } + + pDebug() << Q_FUNC_INFO << newSource.url(); + + stop(); // first call stop as that often is the expected state + // for setting a new URL + + d->mediaSource = newSource; +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + d->kiofallback = 0; // kiofallback auto-deletes +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +//X if (url.scheme() == "http") { +//X d->kiofallback = Platform::createMediaStream(url, this); +//X if (d->kiofallback) { +//X ... +//X return; +//X } +//X } + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (d->mediaSource.type() == MediaSource::Stream) { + Q_ASSERT(d->mediaSource.stream()); + d->mediaSource.stream()->d_func()->setMediaObjectPrivate(d); + } +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + + INTERFACE_CALL(setSource(d->mediaSource)); +} + +void MediaObject::clear() +{ + K_D(MediaObject); + d->sourceQueue.clear(); + setCurrentSource(MediaSource()); +} + +QList<MediaSource> MediaObject::queue() const +{ + K_D(const MediaObject); + return d->sourceQueue; +} + +void MediaObject::setQueue(const QList<MediaSource> &sources) +{ + K_D(MediaObject); + d->sourceQueue.clear(); + enqueue(sources); +} + +void MediaObject::setQueue(const QList<QUrl> &urls) +{ + K_D(MediaObject); + d->sourceQueue.clear(); + enqueue(urls); +} + +void MediaObject::enqueue(const MediaSource &source) +{ + K_D(MediaObject); + if (!isPlayable(d->mediaSource.type())) { + // the current source is nothing valid so this source needs to become the current one + setCurrentSource(source); + } else { + d->sourceQueue << source; + } +} + +void MediaObject::enqueue(const QList<MediaSource> &sources) +{ + for (int i = 0; i < sources.count(); ++i) { + enqueue(sources.at(i)); + } +} + +void MediaObject::enqueue(const QList<QUrl> &urls) +{ + for (int i = 0; i < urls.count(); ++i) { + enqueue(urls.at(i)); + } +} + +void MediaObject::clearQueue() +{ + K_D(MediaObject); + d->sourceQueue.clear(); +} + +bool MediaObjectPrivate::aboutToDeleteBackendObject() +{ + //pDebug() << Q_FUNC_INFO; + prefinishMark = pINTERFACE_CALL(prefinishMark()); + transitionTime = pINTERFACE_CALL(transitionTime()); + //pDebug() << Q_FUNC_INFO; + if (m_backendObject) { + state = pINTERFACE_CALL(state()); + currentTime = pINTERFACE_CALL(currentTime()); + tickInterval = pINTERFACE_CALL(tickInterval()); + } + return true; +} + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM +void MediaObjectPrivate::streamError(Phonon::ErrorType type, const QString &text) +{ + Q_Q(MediaObject); + State lastState = q->state(); + errorOverride = true; + errorType = type; + errorString = text; + state = ErrorState; + QMetaObject::invokeMethod(q, "stateChanged", Qt::QueuedConnection, Q_ARG(Phonon::State, Phonon::ErrorState), Q_ARG(Phonon::State, lastState)); + //emit q->stateChanged(ErrorState, lastState); +} + +void MediaObjectPrivate::_k_stateChanged(Phonon::State newstate, Phonon::State oldstate) +{ + Q_Q(MediaObject); + if (mediaSource.type() != MediaSource::Url) { + // special handling only necessary for URLs because of the fallback + emit q->stateChanged(newstate, oldstate); + return; + } + + if (errorOverride) { + errorOverride = false; + if (newstate == ErrorState) { + return; + } + oldstate = ErrorState; + } + + // backend MediaObject reached ErrorState, try a KioMediaSource + if (newstate == Phonon::ErrorState && !kiofallback) { + kiofallback = Platform::createMediaStream(mediaSource.url(), q); + if (!kiofallback) { + pDebug() << "backend MediaObject reached ErrorState, no KIO fallback available"; + emit q->stateChanged(newstate, oldstate); + return; + } + pDebug() << "backend MediaObject reached ErrorState, trying Platform::createMediaStream now"; + ignoreLoadingToBufferingStateChange = false; + ignoreErrorToLoadingStateChange = false; + switch (oldstate) { + case Phonon::BufferingState: + // play() has already been called, we need to make sure it is called + // on the backend with the KioMediaStream MediaSource now, too + ignoreLoadingToBufferingStateChange = true; + break; + case Phonon::LoadingState: + ignoreErrorToLoadingStateChange = true; + // no extras + break; + default: + pError() << "backend MediaObject reached ErrorState after " << oldstate + << ". It seems a KioMediaStream will not help here, trying anyway."; + emit q->stateChanged(Phonon::LoadingState, oldstate); + break; + } + kiofallback->d_func()->setMediaObjectPrivate(this); + MediaSource mediaSource(kiofallback); + mediaSource.setAutoDelete(true); + pINTERFACE_CALL(setSource(mediaSource)); + if (oldstate == Phonon::BufferingState) { + q->play(); + } + return; + } else if (ignoreLoadingToBufferingStateChange && + kiofallback && + oldstate == Phonon::LoadingState) { + if (newstate != Phonon::BufferingState) { + emit q->stateChanged(newstate, Phonon::BufferingState); + } + return; + } else if (ignoreErrorToLoadingStateChange && kiofallback && oldstate == ErrorState) { + if (newstate != LoadingState) { + emit q->stateChanged(newstate, Phonon::LoadingState); + } + return; + } + + emit q->stateChanged(newstate, oldstate); +} +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +void MediaObjectPrivate::_k_aboutToFinish() +{ + Q_Q(MediaObject); + pDebug() << Q_FUNC_INFO; + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + kiofallback = 0; // kiofallback auto-deletes +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + + if (sourceQueue.isEmpty()) { + emit q->aboutToFinish(); + if (sourceQueue.isEmpty()) { + return; + } + } + + mediaSource = sourceQueue.head(); + pINTERFACE_CALL(setNextSource(mediaSource)); +} + +void MediaObjectPrivate::_k_currentSourceChanged(const MediaSource &source) +{ + Q_Q(MediaObject); + pDebug() << Q_FUNC_INFO; + + if (!sourceQueue.isEmpty() && sourceQueue.head() == source) + sourceQueue.dequeue(); + + emit q->currentSourceChanged(source); +} + +void MediaObjectPrivate::setupBackendObject() +{ + Q_Q(MediaObject); + Q_ASSERT(m_backendObject); + //pDebug() << Q_FUNC_INFO; + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), q, SLOT(_k_stateChanged(Phonon::State, Phonon::State))); +#else + QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), q, SIGNAL(stateChanged(Phonon::State, Phonon::State))); +#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM + QObject::connect(m_backendObject, SIGNAL(tick(qint64)), q, SIGNAL(tick(qint64))); + QObject::connect(m_backendObject, SIGNAL(seekableChanged(bool)), q, SIGNAL(seekableChanged(bool))); +#ifndef QT_NO_PHONON_VIDEO + QObject::connect(m_backendObject, SIGNAL(hasVideoChanged(bool)), q, SIGNAL(hasVideoChanged(bool))); +#endif //QT_NO_PHONON_VIDEO + QObject::connect(m_backendObject, SIGNAL(bufferStatus(int)), q, SIGNAL(bufferStatus(int))); + QObject::connect(m_backendObject, SIGNAL(finished()), q, SIGNAL(finished())); + QObject::connect(m_backendObject, SIGNAL(aboutToFinish()), q, SLOT(_k_aboutToFinish())); + QObject::connect(m_backendObject, SIGNAL(prefinishMarkReached(qint32)), q, SIGNAL(prefinishMarkReached(qint32))); + QObject::connect(m_backendObject, SIGNAL(totalTimeChanged(qint64)), q, SIGNAL(totalTimeChanged(qint64))); + QObject::connect(m_backendObject, SIGNAL(metaDataChanged(const QMultiMap<QString, QString> &)), + q, SLOT(_k_metaDataChanged(const QMultiMap<QString, QString> &))); + QObject::connect(m_backendObject, SIGNAL(currentSourceChanged(const MediaSource&)), + q, SLOT(_k_currentSourceChanged(const MediaSource&))); + + // set up attributes + pINTERFACE_CALL(setTickInterval(tickInterval)); + pINTERFACE_CALL(setPrefinishMark(prefinishMark)); + pINTERFACE_CALL(setTransitionTime(transitionTime)); + + switch(state) + { + case LoadingState: + case StoppedState: + case ErrorState: + break; + case PlayingState: + case BufferingState: + QTimer::singleShot(0, q, SLOT(_k_resumePlay())); + break; + case PausedState: + QTimer::singleShot(0, q, SLOT(_k_resumePause())); + break; + } + const State backendState = pINTERFACE_CALL(state()); + if (state != backendState && state != ErrorState) { + // careful: if state is ErrorState we might be switching from a + // MediaObject to a ByteStream for KIO fallback. In that case the state + // change to ErrorState was already suppressed. + pDebug() << "emitting a state change because the backend object has been replaced"; + emit q->stateChanged(backendState, state); + state = backendState; + } + +#ifndef QT_NO_PHONON_MEDIACONTROLLER + for (int i = 0 ; i < interfaceList.count(); ++i) { + interfaceList.at(i)->_backendObjectChanged(); + } +#endif //QT_NO_PHONON_MEDIACONTROLLER + + // set up attributes + if (isPlayable(mediaSource.type())) { +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (mediaSource.type() == MediaSource::Stream) { + Q_ASSERT(mediaSource.stream()); + mediaSource.stream()->d_func()->setMediaObjectPrivate(this); + } +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + pINTERFACE_CALL(setSource(mediaSource)); + } +} + +void MediaObjectPrivate::_k_resumePlay() +{ + qobject_cast<MediaObjectInterface *>(m_backendObject)->play(); + if (currentTime > 0) { + qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime); + } +} + +void MediaObjectPrivate::_k_resumePause() +{ + pINTERFACE_CALL(pause()); + if (currentTime > 0) { + qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime); + } +} + +void MediaObjectPrivate::_k_metaDataChanged(const QMultiMap<QString, QString> &newMetaData) +{ + metaData = newMetaData; + emit q_func()->metaDataChanged(); +} + +void MediaObjectPrivate::phononObjectDestroyed(MediaNodePrivate *bp) +{ + // this method is called from Phonon::Base::~Base(), meaning the AudioPath + // dtor has already been called, also virtual functions don't work anymore + // (therefore qobject_cast can only downcast from Base) + Q_ASSERT(bp); + Q_UNUSED(bp); +} + +MediaObject *createPlayer(Phonon::Category category, const MediaSource &source) +{ + MediaObject *mo = new MediaObject; + AudioOutput *ao = new AudioOutput(category, mo); + createPath(mo, ao); + if (isPlayable(source.type())) { + mo->setCurrentSource(source); + } + return mo; +} + +} //namespace Phonon + +QT_END_NAMESPACE + +#include "moc_mediaobject.cpp" + +#undef PHONON_CLASSNAME +#undef PHONON_INTERFACENAME +// vim: sw=4 tw=100 et diff --git a/src/3rdparty/phonon/phonon/mediaobject.dox b/src/3rdparty/phonon/phonon/mediaobject.dox new file mode 100644 index 0000000..cc6fe5f --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediaobject.dox @@ -0,0 +1,71 @@ +/** +\page phonon_MediaObject The MediaObject class + +\section phonon_MediaObject_derived Media Data Producing Class + +There is the class that produces the media data (often called a source in +media frameworks). + +\section phonon_MediaObject_requiredfunctions Required Functions +\li qint32 \ref phonon_MediaObject_prefinishMark "prefinishMark()" +\li void \ref phonon_MediaObject_setPrefinishMark "setPrefinishMark(qint32)" + +\section phonon_MediaObject_optionalfunctions Optional Functions +\li qint64 \ref phonon_MediaObject_remainingTime "remainingTime()" + +\section phonon_MediaObject_signals Signals +\li void \ref phonon_MediaObject_totalTimeChanged "totalTimeChanged(qint64 totalTime)" +\li void \ref phonon_MediaObject_prefinishMarkReached "prefinishMarkReached(qint32 msec)" +\li void \ref phonon_MediaObject_finished "finished()" + +\section phonon_MediaObject_memberdocs Member Function Documentation + +\see \ref phonon_MediaObject_totalTimeChanged + +\subsection phonon_MediaObject_prefinishMark qint32 prefinishMark() +Returns the time in milliseconds the \ref phonon_MediaObject_prefinishMarkReached +"prefinishMarkReached" signal is emitted before the playback if finished and \ref +phonon_MediaObject_finished "finished" is emitted. + +\subsection phonon_MediaObject_setPrefinishMark void setPrefinishMark(qint32 msec) +Sets the time in milliseconds the \ref phonon_MediaObject_prefinishMarkReached +"prefinishMarkReached" signal is emitted before the playback if finished and \ref +phonon_MediaObject_finished "finished" is emitted. + +\param msec The time in milliseconds. If the value is less than or equal to 0 +the \ref phonon_MediaObject_prefinishMarkReached "prefinishMarkReached" signal is disabled. + +\subsection phonon_MediaObject_remainingTime qint64 remainingTime() +Get the remaining time (in milliseconds) of the file currently being played. If +the method is not implemented in the backend the frontend will use the +difference between \link Phonon::MediaObjectInterface::totalTime() MediaObjectInterface::totalTime() \endlink and +\link Phonon::MediaObjectInterface::currentTime() MediaObjectInterface::currentTime() \endlink. + +\section phonon_MediaObject_signaldocs Signals Documentation +\subsection phonon_MediaObject_prefinishMarkReached void prefinishMarkReached(qint32 msec) +Emitted when the file has finished playing on its own. +I.e. it is not emitted if you call stop(), pause() or +load(), but only on end-of-file or a critical error. +void finished() + +\param msec The remaining time until the playback finishes + +\subsection phonon_MediaObject_totalTimeChanged void totalTimeChanged(qint64 totalTime) +This signal is emitted as soon as the length of the media file is +known or has changed. For most non-local media data the length of +the media can only be known after some time. At that time the +totalTime function can not return useful information. You have +to wait for this signal to know the real length. + +\param totalTimeChanged The total time of the media file in milliseconds. + +\see \link Phonon::MediaObjectInterface::totalTime() MediaObjectInterface::totalTime() \endlink + +\subsection phonon_MediaObject_finished void finished() +This signal is emitted when the playback of the media finished (on its own). +It is not emitted if stop() or pause() are called - only on end-of-file or a +critical error (for example the media data stream is corrupted and playback of +the media has to be finished). + +\see \ref phonon_MediaObject_prefinishMarkReached +*/ diff --git a/src/3rdparty/phonon/phonon/mediaobject.h b/src/3rdparty/phonon/phonon/mediaobject.h new file mode 100644 index 0000000..ade966a --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediaobject.h @@ -0,0 +1,623 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#ifndef Phonon_MEDIAOBJECT_H +#define Phonon_MEDIAOBJECT_H + +#include "medianode.h" +#include "mediasource.h" +#include "phonon_export.h" +#include "phonondefs.h" +#include "phononnamespace.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class MediaObjectPrivate; + + /** \class MediaObject mediaobject.h Phonon/MediaObject + * \short Interface for media playback of a given URL. + * + * This class is the most important class in %Phonon. Use it to open a media + * file at an arbitrary location, a CD or DVD or to stream media data from + * the application to the backend. + * + * This class controls the state (play, pause, stop, seek) + * and you can use it to get a lot of information about the media data. + * + * Notice that most functions of this class are asynchronous. + * That means if you call play() the object only starts playing when the + * stateChanged() signal tells you that the object changed into PlayingState. + * The states you can expect are documented for those methods. + * + * A common usage example is the following: + * \code + * media = new MediaObject(this); + * connect(media, SIGNAL(finished()), SLOT(slotFinished()); + * media->setCurrentSource("/home/username/music/filename.ogg"); + * media->play(); + * \endcode + * + * If you want to play more than one media file (one after another) you can + * either tell MediaObject about all those files + * \code + * media->setCurrentSource(":/sounds/startsound.ogg"); + * media->enqueue("/home/username/music/song.mp3"); + * media->enqueue(":/sounds/endsound.ogg"); + * \endcode + * or provide the next file just in time: + * \code + * media->setCurrentSource(":/sounds/startsound.ogg"); + * connect(media, SIGNAL(aboutToFinish()), SLOT(enqueueNextSource())); + * } + * + * void enqueueNextSource() + * { + * media->enqueue("/home/username/music/song.mp3"); + * } + * \endcode + * + * \ingroup Playback + * \ingroup Recording + * \author Matthias Kretz <kretz@kde.org> + */ + class PHONON_EXPORT MediaObject : public QObject, public MediaNode + { + friend class FrontendInterfacePrivate; + Q_OBJECT + K_DECLARE_PRIVATE(MediaObject) + PHONON_OBJECT(MediaObject) + /** + * \brief Defines the time between media sources. + * + * A positive transition time defines a gap of silence between queued + * media sources. + * + * A transition time of 0 ms requests gapless playback (sample precise + * queueing of the next source). + * + * A negative transition time defines a crossfade between the queued + * media sources. + * + * Defaults to 0 (gapless playback). + * + * \warning This feature might not work reliably on every platform. + */ + Q_PROPERTY(qint32 transitionTime READ transitionTime WRITE setTransitionTime) + + /** + * \brief Get a signal before playback finishes. + * + * This property specifies the time in milliseconds the + * prefinishMarkReached signal is + * emitted before the playback finishes. A value of \c 0 disables the + * signal. + * + * Defaults to \c 0 (disabled). + * + * \warning For some media data the total time cannot be determined + * accurately, therefore the accuracy of the prefinishMarkReached signal + * can be bad sometimes. Still, it is better to use this method than to + * look at totalTime() and currentTime() to emulate the behaviour + * because the backend might have more information available than your + * application does through totalTime and currentTime. + * + * \see prefinishMarkReached + */ + Q_PROPERTY(qint32 prefinishMark READ prefinishMark WRITE setPrefinishMark) + + /** + * \brief The time interval in milliseconds between two ticks. + * + * The %tick interval is the time that elapses between the emission of two tick signals. + * If you set the interval to \c 0 the tick signal gets disabled. + * + * Defaults to \c 0 (disabled). + * + * \warning The back-end is free to choose a different tick interval close + * to what you asked for. This means that the following code \em may \em fail: + * \code + * int x = 200; + * media->setTickInterval(x); + * Q_ASSERT(x == producer->tickInterval()); + * \endcode + * On the other hand the following is guaranteed: + * \code + * int x = 200; + * media->setTickInterval(x); + * Q_ASSERT(x >= producer->tickInterval() && + * x <= 2 * producer->tickInterval()); + * \endcode + * + * \see tick + */ + Q_PROPERTY(qint32 tickInterval READ tickInterval WRITE setTickInterval) + public: + /** + * Destroys the MediaObject. + */ + ~MediaObject(); + + /** + * Get the current state. + * + * @return The state of the object. + * + * @see State + * \see stateChanged + */ + State state() const; + + /** + * Check whether the media data includes a video stream. + * + * \warning This information cannot be known immediately. It is best + * to also listen to the hasVideoChanged signal. + * + * \code + * connect(media, SIGNAL(hasVideoChanged(bool)), hasVideoChanged(bool)); + * media->setCurrentSource("somevideo.avi"); + * media->hasVideo(); // returns false; + * } + * + * void hasVideoChanged(bool b) + * { + * // b == true + * media->hasVideo(); // returns true; + * } + * \endcode + * + * \return \c true if the media contains video data. \c false + * otherwise. + * + * \see hasVideoChanged + */ + bool hasVideo() const; + + /** + * Check whether the current media may be seeked. + * + * \warning This information cannot be known immediately. It is best + * to also listen to the seekableChanged signal. + * + * \code + * connect(media, SIGNAL(seekableChanged(bool)), seekableChanged(bool)); + * media->setCurrentSource("somevideo.avi"); + * media->isSeekable(); // returns false; + * } + * + * void seekableChanged(bool b) + * { + * // b == true + * media->isSeekable(); // returns true; + * } + * \endcode + * + * \return \c true when the current media may be seeked. \c false + * otherwise. + * + * \see seekableChanged() + */ + bool isSeekable() const; + + qint32 tickInterval() const; + + /** + * Returns the strings associated with the given \p key. + * + * Backends should use the keys specified in the Ogg Vorbis + * documentation: http://xiph.org/vorbis/doc/v-comment.html + * + * Therefore the following should work with every backend: + * + * A typical usage looks like this: + * \code + * setMetaArtist (media->metaData("ARTIST" )); + * setMetaAlbum (media->metaData("ALBUM" )); + * setMetaTitle (media->metaData("TITLE" )); + * setMetaDate (media->metaData("DATE" )); + * setMetaGenre (media->metaData("GENRE" )); + * setMetaTrack (media->metaData("TRACKNUMBER")); + * setMetaComment(media->metaData("DESCRIPTION")); + * \endcode + * + * For Audio CDs you can query + * \code + * metaData("MUSICBRAINZ_DISCID"); + * \endcode + * to get a DiscID hash that you can use with the MusicBrainz + * service: + * http://musicbrainz.org/doc/ClientHOWTO + */ + QStringList metaData(const QString &key) const; + + /** + * Returns the strings associated with the given \p key. + * + * Same as above except that the keys are defined in the + * Phonon::MetaData enum. + */ + QStringList metaData(Phonon::MetaData key) const; + + /** + * Returns all meta data. + */ + QMultiMap<QString, QString> metaData() const; + + /** + * Returns a human-readable description of the last error that occurred. + */ + QString errorString() const; + + /** + * Tells your program what to do about the error. + * + * \see Phonon::ErrorType + */ + ErrorType errorType() const; + + /** + * Returns the current media source. + * + * \see setCurrentSource + */ + MediaSource currentSource() const; + + /** + * Set the media source the MediaObject should use. + * + * \param source The MediaSource object to the media data. You can + * just as well use a QUrl or QString (for a local file) here. + * Setting an empty (invalid) source, will stop and remove the + * current source. + * + * \code + * QUrl url("http://www.example.com/music.ogg"); + * media->setCurrentSource(url); + * \endcode + * + * \see currentSource + */ + void setCurrentSource(const MediaSource &source); + + /** + * Returns the queued media sources. This list does not include + * the current source (returned by currentSource). + */ + QList<MediaSource> queue() const; + + /** + * Set the MediaSources to play when the current media has finished. + * + * This function will overwrite the current queue. + * + * \see clearQueue + * \see enqueue + */ + void setQueue(const QList<MediaSource> &sources); + + /** + * Set the MediaSources to play when the current media has finished. + * + * This function overwrites the current queue. + * + * \see clearQueue + * \see enqueue + */ + void setQueue(const QList<QUrl> &urls); + + /** + * Appends one source to the queue. Use this function to provide + * the next source just in time after the aboutToFinish signal was + * emitted. + * + * \see aboutToFinish + * \see setQueue + * \see clearQueue + */ + void enqueue(const MediaSource &source); + + /** + * Appends multiple sources to the queue. + * + * \see setQueue + * \see clearQueue + */ + void enqueue(const QList<MediaSource> &sources); + + /** + * Appends multiple sources to the queue. + * + * \see setQueue + * \see clearQueue + */ + void enqueue(const QList<QUrl> &urls); + + /** + * Clears the queue of sources. + */ + void clearQueue(); + + /** + * Get the current time (in milliseconds) of the file currently being played. + * + * \return The current time in milliseconds. + * + * \see tick + */ + qint64 currentTime() const; + + /** + * Get the total time (in milliseconds) of the file currently being played. + * + * \return The total time in milliseconds. + * + * \see totalTimeChanged + */ + qint64 totalTime() const; + + /** + * Get the remaining time (in milliseconds) of the file currently being played. + * + * \return The remaining time in milliseconds. + */ + qint64 remainingTime() const; + + qint32 prefinishMark() const; + void setPrefinishMark(qint32 msecToEnd); + + qint32 transitionTime() const; + void setTransitionTime(qint32 msec); + + public Q_SLOTS: + + void setTickInterval(qint32 newTickInterval); + + /** + * Requests playback of the media data to start. Playback only + * starts when stateChanged() signals that it goes into PlayingState, + * though. + * + * \par Possible states right after this call: + * \li BufferingState + * \li PlayingState + * \li ErrorState + */ + void play(); + + /** + * Requests playback to pause. If it was paused before nothing changes. + * + * \par Possible states right after this call: + * \li PlayingState + * \li PausedState + * \li ErrorState + */ + void pause(); + + /** + * Requests playback to stop. If it was stopped before nothing changes. + * + * \par Possible states right after this call: + * \li the state it was in before (e.g. PlayingState) + * \li StoppedState + * \li ErrorState + */ + void stop(); + + /** + * Requests a seek to the time indicated. + * + * You can only seek if state() == PlayingState, BufferingState or PausedState. + * + * The call is asynchronous, so currentTime can still be the old + * value right after this method was called. If all you need is a + * slider that shows the current position and allows the user to + * seek use the class SeekSlider. + * + * @param time The time in milliseconds where to continue playing. + * + * \par Possible states right after this call: + * \li BufferingState + * \li PlayingState + * \li ErrorState + * + * \see SeekSlider + */ + void seek(qint64 time); + + /** + * Stops and removes all playing and enqueued media sources. + * + * \see setCurrentSource + */ + void clear(); + + Q_SIGNALS: + /** + * Emitted when the state of the MediaObject has changed. + * + * @param newstate The state the Player is in now. + * @param oldstate The state the Player was in before. + */ + void stateChanged(Phonon::State newstate, Phonon::State oldstate); + + /** + * This signal gets emitted every tickInterval milliseconds. + * + * @param time The position of the media file in milliseconds. + * + * @see setTickInterval, tickInterval + */ + void tick(qint64 time); + + /** + * This signal is emitted whenever the audio/video data that is + * being played is associated with new meta data. E.g. for radio + * streams this happens when the next song is played. + * + * You can get the new meta data with the metaData methods. + */ + void metaDataChanged(); + + /** + * Emitted whenever the return value of isSeekable() changes. + * + * Normally you'll check isSeekable() first and then let this signal + * tell you whether seeking is possible now or not. That way you + * don't have to poll isSeekable(). + * + * \param isSeekable \p true if the stream is seekable (i.e. calling + * seek() works) + * \p false if the stream is not seekable (i.e. + * all calls to seek() will be ignored) + */ + void seekableChanged(bool isSeekable); + + /** + * Emitted whenever the return value of hasVideo() changes. + * + * Normally you'll check hasVideo() first and then let this signal + * tell you whether video is available now or not. That way you + * don't have to poll hasVideo(). + * + * \param hasVideo \p true The stream contains video and adding a + * VideoWidget will show a video. + * \p false There is no video data in the stream and + * adding a VideoWidget will show an empty (black) + * VideoWidget. + */ +#ifndef QT_NO_PHONON_VIDEO + void hasVideoChanged(bool hasVideo); +#endif //QT_NO_PHONON_VIDEO + + /** + * Tells about the status of the buffer. + * + * You can use this signal to show a progress bar to the user when + * in BufferingState: + * + * \code + * progressBar->setRange(0, 100); // this is the default + * connect(media, SIGNAL(bufferStatus(int)), progressBar, SLOT(setValue(int))); + * \endcode + * + * \param percentFilled A number between 0 and 100 telling you how + * much the buffer is filled. + */ // other names: bufferingProgress + void bufferStatus(int percentFilled); + + /** + * Emitted when the object has finished playback. + * It is not emitted if you call stop(), pause() or + * load(), but only on end-of-queue or a critical error. + * + * \warning This signal is not emitted when the current source has + * finished and there's another source in the queue. It is only + * emitted when the queue is empty. + * + * \see currentSourceChanged + * \see aboutToFinish + * \see prefinishMarkReached + */ + void finished(); + + /** + * Emitted when the MediaObject makes a transition to the next + * MediaSource in the queue(). + * + * In other words, it is emitted when an individual MediaSource is + * finished. + * + * \param newSource The source that starts to play at the time the + * signal is emitted. + */ + void currentSourceChanged(const Phonon::MediaSource &newSource); + + /** + * Emitted before the playback of the whole queue stops. When this + * signal is emitted you still have time to provide the next + * MediaSource (using enqueue()) so that playback continues. + * + * This signal can be used to provide the next MediaSource just in + * time for the transition still to work. + * + * \see enqueue + */ + void aboutToFinish(); + + /** + * Emitted when there are only \p msecToEnd milliseconds left + * for playback. + * + * \param msecToEnd The remaining time until the playback queue finishes. + * + * \warning This signal is not emitted when there is another source in the queue. + * It is only emitted when the queue is empty. + * + * \see setPrefinishMark + * \see prefinishMark + * \see aboutToFinish + * \see finished + */ + void prefinishMarkReached(qint32 msecToEnd); + + /** + * This signal is emitted as soon as the total time of the media file is + * known or has changed. For most non-local media data the total + * time of the media can only be known after some time. Initially the + * totalTime function can not return useful information. You have + * to wait for this signal to know the real total time. + * + * \param newTotalTime The length of the media file in milliseconds. + * + * \see totalTime + */ + void totalTimeChanged(qint64 newTotalTime); + + protected: + //MediaObject(Phonon::MediaObjectPrivate &dd, QObject *parent); + + private: + Q_PRIVATE_SLOT(k_func(), void _k_resumePlay()) + Q_PRIVATE_SLOT(k_func(), void _k_resumePause()) + Q_PRIVATE_SLOT(k_func(), void _k_metaDataChanged(const QMultiMap<QString, QString> &)) +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + Q_PRIVATE_SLOT(k_func(), void _k_stateChanged(Phonon::State, Phonon::State)) +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + Q_PRIVATE_SLOT(k_func(), void _k_aboutToFinish()) + Q_PRIVATE_SLOT(k_func(), void _k_currentSourceChanged(const MediaSource &)) + }; + + /** + * Convenience function to create a MediaObject and AudioOutput connected by + * a path. + */ + PHONON_EXPORT MediaObject *createPlayer(Phonon::Category category, const MediaSource &source = MediaSource()); +} //namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_MEDIAOBJECT_H diff --git a/src/3rdparty/phonon/phonon/mediaobject_p.h b/src/3rdparty/phonon/phonon/mediaobject_p.h new file mode 100644 index 0000000..c164490 --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediaobject_p.h @@ -0,0 +1,113 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef MEDIAOBJECT_P_H +#define MEDIAOBJECT_P_H + +#include "mediaobject.h" +#include "medianode_p.h" +#include <QtCore/QString> +#include "medianodedestructionhandler_p.h" +#include "mediasource.h" +#include <QtCore/QQueue> + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +class KioFallback; +class KioFallbackImpl; +class FrontendInterfacePrivate; + +class MediaObjectPrivate : public MediaNodePrivate, private MediaNodeDestructionHandler +{ + friend class KioFallbackImpl; + friend class AbstractMediaStream; + friend class AbstractMediaStreamPrivate; + Q_DECLARE_PUBLIC(MediaObject) + public: + virtual QObject *qObject() { return q_func(); } + QList<FrontendInterfacePrivate *> interfaceList; + protected: + virtual bool aboutToDeleteBackendObject(); + virtual void createBackendObject(); + virtual void phononObjectDestroyed(MediaNodePrivate *); + PHONON_EXPORT void setupBackendObject(); + + void _k_resumePlay(); + void _k_resumePause(); + void _k_metaDataChanged(const QMultiMap<QString, QString> &); + void _k_aboutToFinish(); + void _k_currentSourceChanged(const MediaSource &); +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + void streamError(Phonon::ErrorType, const QString &); + PHONON_EXPORT void _k_stateChanged(Phonon::State, Phonon::State); +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + + MediaObjectPrivate() + : currentTime(0), + tickInterval(0), + metaData(), + errorString(), + prefinishMark(0), + transitionTime(0), // gapless playback +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + kiofallback(0), +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + state(Phonon::LoadingState) +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + , errorType(Phonon::NormalError), + errorOverride(false), + ignoreLoadingToBufferingStateChange(false), + ignoreErrorToLoadingStateChange(false) +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + { + } + + qint64 currentTime; + qint32 tickInterval; + QMultiMap<QString, QString> metaData; + QString errorString; + qint32 prefinishMark; + qint32 transitionTime; +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + AbstractMediaStream *kiofallback; +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + State state +#ifdef QT_NO_PHONON_ABSTRACTMEDIASTREAM + ; +#else + : 8; + ErrorType errorType : 4; + bool errorOverride : 1; + bool ignoreLoadingToBufferingStateChange : 1; + bool ignoreErrorToLoadingStateChange : 1; +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + MediaSource mediaSource; + QQueue<MediaSource> sourceQueue; +}; +} + +QT_END_NAMESPACE + +#endif // MEDIAOBJECT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/mediaobjectinterface.h b/src/3rdparty/phonon/phonon/mediaobjectinterface.h new file mode 100644 index 0000000..26c4c8e --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediaobjectinterface.h @@ -0,0 +1,242 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_MEDIAOBJECTINTERFACE_H +#define PHONON_MEDIAOBJECTINTERFACE_H + +#include "mediaobject.h" +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +class StreamInterface; + +/** \class MediaObjectInterface mediaobjectinterface.h Phonon/MediaObjectInterface + * \short Backend interface for media sources. + * + * The backend implementation has to provide two signals, that are not defined + * in this interface: + * <ul> + * <li>\anchor phonon_MediaObjectInterface_stateChanged + * <b>void stateChanged(\ref Phonon::State newstate, \ref Phonon::State oldstate)</b> + * + * Emitted when the state of the MediaObject has changed. + * In case you're not interested in the old state you can also + * connect to a slot that only has one State argument. + * + * \param newstate The state the Player is in now. + * \param oldstate The state the Player was in before. + * </li> + * <li>\anchor phonon_MediaObjectInterface_tick + * <b>void tick(qint64 time)</b> + * + * This signal gets emitted every tickInterval milliseconds. + * + * \param time The position of the media file in milliseconds. + * + * \see setTickInterval() + * \see tickInterval() + * </li> + * </ul> + * + * \author Matthias Kretz <kretz@kde.org> + * \see MediaObject + */ +class MediaObjectInterface +{ + public: + virtual ~MediaObjectInterface() {} + + /** + * Requests the playback to start. + * + * This method is only called if the state transition to \ref PlayingState is possible. + * + * The backend should react immediately + * by either going into \ref PlayingState or \ref BufferingState if the + * former is not possible. + */ + virtual void play() = 0; + + /** + * Requests the playback to pause. + * + * This method is only called if the state transition to \ref PausedState is possible. + * + * The backend should react as fast as possible. Go to \ref PausedState + * as soon as playback is paused. + */ + virtual void pause() = 0; + + /** + * Requests the playback to be stopped. + * + * This method is only called if the state transition to \ref StoppedState is possible. + * + * The backend should react as fast as possible. Go to \ref StoppedState + * as soon as playback is stopped. + * + * A subsequent call to play() will start playback at the beginning of + * the media. + */ + virtual void stop() = 0; + + /** + * Requests the playback to be seeked to the given time. + * + * The backend does not have to finish seeking while in this function + * (i.e. the backend does not need to block the thread until the seek is + * finished; even worse it might lead to deadlocks when using a + * ByteStream which gets its data from the thread this function would + * block). + * + * As soon as the seek is done the currentTime() function and + * the tick() signal will report it. + * + * \param milliseconds The time where playback should seek to in + * milliseconds. + */ + virtual void seek(qint64 milliseconds) = 0; + + /** + * Return the time interval in milliseconds between two ticks. + * + * \returns Returns the tick interval that it was set to (might not + * be the same as you asked for). + */ + virtual qint32 tickInterval() const = 0; + /** + * Change the interval the tick signal is emitted. If you set \p + * interval to 0 the signal gets disabled. + * + * \param interval tick interval in milliseconds + * + * \returns Returns the tick interval that it was set to (might not + * be the same as you asked for). + */ + virtual void setTickInterval(qint32 interval) = 0; + + /** + * Check whether the media data includes a video stream. + * + * \return returns \p true if the media contains video data + */ + virtual bool hasVideo() const = 0; + /** + * If the current media may be seeked returns true. + * + * \returns whether the current media may be seeked. + */ + virtual bool isSeekable() const = 0; + /** + * Get the current time (in milliseconds) of the file currently being played. + */ + virtual qint64 currentTime() const = 0; + /** + * Get the current state. + */ + virtual Phonon::State state() const = 0; + + /** + * A translated string describing the error. + */ + virtual QString errorString() const = 0; + + /** + * Tells your program what to do about the error. + * + * \see Phonon::ErrorType + */ + virtual Phonon::ErrorType errorType() const = 0; + + /** + * Returns the total time of the media in milliseconds. + * + * If the total time is not know return -1. Do not block until it is + * known, instead emit the totalTimeChanged signal as soon as the total + * time is known or changes. + */ + virtual qint64 totalTime() const = 0; + + /** + * Returns the current source. + */ + virtual MediaSource source() const = 0; + + /** + * Sets the current source. When this function is called the MediaObject is + * expected to stop all current activity and start loading the new + * source (i.e. go into LoadingState). + * + * It is expected that the + * backend now starts preloading the media data, filling the audio + * and video buffers and making all media meta data available. It + * will also trigger the totalTimeChanged signal. + * + * If the backend does not know how to handle the source it needs to + * change state to Phonon::ErrorState. Don't bother about handling KIO + * URLs. It is enough to handle AbstractMediaStream sources correctly. + * + * \warning Keep the MediaSource object around as long as the backend + * uses the AbstractMediaStream returned by the MediaSource. In case + * that no other reference to the MediaSource exists and it is set to + * MediaSource::autoDelete, the AbstractMediaStream is deleted when the + * last MediaSource ref is deleted. + */ + virtual void setSource(const MediaSource &) = 0; + + /** + * Sets the next source to be used for transitions. When a next source + * is set playback should continue with the new source. In that case + * finished and prefinishMarkReached are not emitted. + * + * \param source The source to transition to (crossfade/gapless/gap). If + * \p source is an invalid MediaSource object then the queue is empty + * and the playback should stop normally. + * + * \warning Keep the MediaSource object around as long as the backend + * uses the AbstractMediaStream returned by the MediaSource. In case + * that no other reference to the MediaSource exists and it is set to + * MediaSource::autoDelete, the AbstractMediaStream is deleted when the + * last MediaSource ref is deleted. + */ + virtual void setNextSource(const MediaSource &source) = 0; + + virtual qint64 remainingTime() const { return totalTime() - currentTime(); } + virtual qint32 prefinishMark() const = 0; + virtual void setPrefinishMark(qint32) = 0; + + virtual qint32 transitionTime() const = 0; + virtual void setTransitionTime(qint32) = 0; +}; +} + +Q_DECLARE_INTERFACE(Phonon::MediaObjectInterface, "MediaObjectInterface3.phonon.kde.org") + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_MEDIAOBJECTINTERFACE_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/mediasource.cpp b/src/3rdparty/phonon/phonon/mediasource.cpp new file mode 100644 index 0000000..d70b38b --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediasource.cpp @@ -0,0 +1,237 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "mediasource.h" +#include "mediasource_p.h" +#include "iodevicestream_p.h" +#include "abstractmediastream_p.h" + +#include <QtCore/QFileInfo> +#include <QtCore/QFile> +#include <QtCore/QFSFileEngine> + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +MediaSource::MediaSource(MediaSourcePrivate &dd) + : d(&dd) +{ +} + +MediaSource::MediaSource() + : d(new MediaSourcePrivate(Empty)) +{ +} + +MediaSource::MediaSource(const QString &filename) + : d(new MediaSourcePrivate(LocalFile)) +{ + const QFileInfo fileInfo(filename); + if (fileInfo.exists()) { + bool localFs = QAbstractFileEngine::LocalDiskFlag & QFSFileEngine(filename).fileFlags(QAbstractFileEngine::LocalDiskFlag); + if (localFs && !filename.startsWith(QLatin1String(":/")) && !filename.startsWith(QLatin1String("qrc://"))) { + d->url = QUrl::fromLocalFile(fileInfo.absoluteFilePath()); + } else { +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + // it's a Qt resource -> use QFile + d->type = Stream; + d->ioDevice = new QFile(filename); + d->setStream(new IODeviceStream(d->ioDevice, d->ioDevice)); + d->url = QUrl::fromLocalFile(fileInfo.absoluteFilePath()); +#else + d->type = Invalid; +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + } + } else { + d->url = filename; + if (d->url.isValid()) { + d->type = Url; + } else { + d->type = Invalid; + } + } +} + +MediaSource::MediaSource(const QUrl &url) + : d(new MediaSourcePrivate(Url)) +{ + if (url.isValid()) { + d->url = url; + } else { + d->type = Invalid; + } +} + +MediaSource::MediaSource(Phonon::DiscType dt, const QString &deviceName) + : d(new MediaSourcePrivate(Disc)) +{ + if (dt == NoDisc) { + d->type = Invalid; + return; + } + d->discType = dt; + d->deviceName = deviceName; +} + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM +MediaSource::MediaSource(AbstractMediaStream *stream) + : d(new MediaSourcePrivate(Stream)) +{ + if (stream) { + d->setStream(stream); + } else { + d->type = Invalid; + } +} + +MediaSource::MediaSource(QIODevice *ioDevice) + : d(new MediaSourcePrivate(Stream)) +{ + if (ioDevice) { + d->setStream(new IODeviceStream(ioDevice, ioDevice)); + d->ioDevice = ioDevice; + } else { + d->type = Invalid; + } +} +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +/* post 4.0 +MediaSource::MediaSource(const QList<MediaSource> &mediaList) + : d(new MediaSourcePrivate(Link)) +{ + d->linkedSources = mediaList; + foreach (MediaSource ms, mediaList) { + Q_ASSERT(ms.type() != Link); + } +} + +QList<MediaSource> MediaSource::substreams() const +{ + return d->linkedSources; +} +*/ + +MediaSource::~MediaSource() +{ +} + +MediaSourcePrivate::~MediaSourcePrivate() +{ +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (autoDelete) { + //here we use deleteLater because this object + //might be destroyed from another thread + if (stream) + stream->deleteLater(); + if (ioDevice) + ioDevice->deleteLater(); + } +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM +} + +MediaSource::MediaSource(const MediaSource &rhs) + : d(rhs.d) +{ +} + +MediaSource &MediaSource::operator=(const MediaSource &rhs) +{ + d = rhs.d; + return *this; +} + +bool MediaSource::operator==(const MediaSource &rhs) const +{ + return d == rhs.d; +} + +void MediaSource::setAutoDelete(bool autoDelete) +{ + d->autoDelete = autoDelete; +} + +bool MediaSource::autoDelete() const +{ + return d->autoDelete; +} + +MediaSource::Type MediaSource::type() const +{ +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + if (d->type == Stream && d->stream == 0) { + return Invalid; + } +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + return d->type; +} + +QString MediaSource::fileName() const +{ + return d->url.toLocalFile(); +} + +QUrl MediaSource::url() const +{ + return d->url; +} + +Phonon::DiscType MediaSource::discType() const +{ + return d->discType; +} + +QString MediaSource::deviceName() const +{ + return d->deviceName; +} + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM +AbstractMediaStream *MediaSource::stream() const +{ + return d->stream; +} + +void MediaSourcePrivate::setStream(AbstractMediaStream *s) +{ + stream = s; +} +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + + +//X AudioCaptureDevice MediaSource::audioCaptureDevice() const +//X { +//X return d->audioCaptureDevice; +//X } +//X +//X VideoCaptureDevice MediaSource::videoCaptureDevice() const +//X { +//X return d->videoCaptureDevice; +//X } + +} // namespace Phonon + +QT_END_NAMESPACE + +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/mediasource.h b/src/3rdparty/phonon/phonon/mediasource.h new file mode 100644 index 0000000..4cddbad --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediasource.h @@ -0,0 +1,279 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_MEDIASOURCE_H +#define PHONON_MEDIASOURCE_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include "objectdescription.h" +#include <QtCore/QSharedData> +#include <QtCore/QString> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QUrl; +class QIODevice; + +namespace Phonon +{ + +class MediaSourcePrivate; +class AbstractMediaStream; + +/** \class MediaSource mediasource.h Phonon/MediaSource + * Note that all constructors of this class are implicit, so that you can simply write + * \code + * MediaObject m; + * QString fileName("/home/foo/bar.ogg"); + * QUrl url("http://www.example.com/stream.mp3"); + * QBuffer *someBuffer; + * m.setCurrentSource(fileName); + * m.setCurrentSource(url); + * m.setCurrentSource(someBuffer); + * m.setCurrentSource(Phonon::Cd); + * \endcode + * + * \ingroup Playback + * \ingroup Recording + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT MediaSource +{ + friend class StreamInterface; + public: + /** + * Identifies the type of media described by the MediaSource object. + * + * \see MediaSource::type() + */ + enum Type { + /** + * The MediaSource object does not describe any valid source. + */ + Invalid = -1, + /** + * The MediaSource object describes a local file. + */ + LocalFile, + /** + * The MediaSource object describes a URL, which can be both a local file and a file on + * the network. + */ + Url, + /** + * The MediaSource object describes a disc. + */ + Disc, + /** + * The MediaSource object describes a data stream. + * + * This is also the type used for QIODevices. + * + * \see AbstractMediaStream + */ + Stream, + /** + * An empty MediaSource. + * + * It can be used to unload the current media from a MediaObject. + * + * \see MediaSource() + */ + Empty +/* post 4.0: + / ** + * Links multiple MediaSource objects together. + * / + Link +*/ + }; + + /** + * Creates an empty MediaSource. + * + * An empty MediaSource is considered valid and can be set on a MediaObject to unload its + * current media. + * + * \see Empty + */ + MediaSource(); + + /** + * Creates a MediaSource object for a local file or a Qt resource. + * + * \param fileName file name of a local media file or a Qt resource that was compiled in. + */ + MediaSource(const QString &fileName); //krazy:exclude=explicit + + /** + * Creates a MediaSource object for a URL. + * + * \param url URL to a media file or stream. + */ + MediaSource(const QUrl &url); //krazy:exclude=explicit + + /** + * Creates a MediaSource object for discs. + * + * \param discType See \ref DiscType + * \param deviceName A platform dependent device name. This can be useful if the computer + * has more than one CD drive. It is recommended to use Solid to retrieve the device name in + * a portable way. + */ + MediaSource(Phonon::DiscType discType, const QString &deviceName = QString()); //krazy:exclude=explicit + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + /** + * Creates a MediaSource object for a data stream. + * + * Your application can provide the media data by subclassing AbstractMediaStream and + * passing a pointer to that object. %Phonon will never delete the \p stream. + * + * \param stream The AbstractMediaStream subclass to provide the media data. + * + * \see setAutoDelete + */ + MediaSource(AbstractMediaStream *stream); //krazy:exclude=explicit + + /** + * Creates a MediaSource object for a QIODevice. + * + * This constructor can be very handy in the combination of QByteArray and QBuffer. + * + * \param ioDevice An arbitrary readable QIODevice subclass. If the device is not opened + * MediaSource will open it as QIODevice::ReadOnly. Sequential I/O devices are possible, + * too. For those MediaObject::isSeekable() will have to return false obviously. + * + * \see setAutoDelete + */ + MediaSource(QIODevice *ioDevice); //krazy:exclude=explicit +#endif + + /** + * Creates a MediaSource object for capture devices. + */ + //MediaSource(const AudioCaptureDevice &, const VideoCaptureDevice &); + + /** + * Destroys the MediaSource object. + */ + ~MediaSource(); + + /** + * Constructs a copy of \p rhs. + * + * This constructor is fast thanks to explicit sharing. + */ + MediaSource(const MediaSource &rhs); + + /** + * Assigns \p rhs to this MediaSource and returns a reference to this MediaSource. + * + * This operation is fast thanks to explicit sharing. + */ + MediaSource &operator=(const MediaSource &rhs); + + /** + * Returns \p true if this MediaSource is equal to \p rhs; otherwise returns \p false. + */ + bool operator==(const MediaSource &rhs) const; + + /** + * Tell the MediaSource to take ownership of the AbstractMediaStream or QIODevice that was + * passed in the constructor. + * + * The default setting is \p false, for safety. If you turn it on, you should only access + * the AbstractMediaStream/QIODevice object as long as you yourself keep a MediaSource + * object around. As long as you keep the MediaSource object wrapping the stream/device + * the object will not get deleted. + * + * \see autoDelete + */ + void setAutoDelete(bool enable); + + /** + * Returns the setting of the auto-delete option. The default is \p false. + * + * \see setAutoDelete + */ + bool autoDelete() const; + + /** + * Returns the type of the MediaSource (depends on the constructor that was used). + * + * \see Type + */ + Type type() const; + + /** + * Returns the file name of the MediaSource if type() == LocalFile; otherwise returns + * QString(). + */ + QString fileName() const; + + /** + * Returns the url of the MediaSource if type() == URL or type() == LocalFile; otherwise + * returns QUrl(). + */ + QUrl url() const; + + /** + * Returns the disc type of the MediaSource if type() == Disc; otherwise returns \ref + * NoDisc. + */ + Phonon::DiscType discType() const; + + /** + * Returns the device name of the MediaSource if type() == Disc; otherwise returns + * QString(). + */ + QString deviceName() const; + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + /** + * Returns the media stream of the MediaSource if type() == Stream; otherwise returns 0. + * QIODevices are handled as streams, too. + */ + AbstractMediaStream *stream() const; +#endif + + //AudioCaptureDevice audioCaptureDevice() const; + //VideoCaptureDevice videoCaptureDevice() const; + +/* post 4.0: + MediaSource(const QList<MediaSource> &mediaList); + QList<MediaSource> substreams() const; +*/ + + protected: + QExplicitlySharedDataPointer<MediaSourcePrivate> d; + MediaSource(MediaSourcePrivate &); +}; + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_MEDIASOURCE_H diff --git a/src/3rdparty/phonon/phonon/mediasource_p.h b/src/3rdparty/phonon/phonon/mediasource_p.h new file mode 100644 index 0000000..46caef3 --- /dev/null +++ b/src/3rdparty/phonon/phonon/mediasource_p.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef MEDIASOURCE_P_H +#define MEDIASOURCE_P_H + +#include "mediasource.h" +#include "objectdescription.h" +#include "abstractmediastream.h" + +#include <QtCore/QUrl> +#include <QtCore/QString> +#include <QtCore/QSharedData> +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +class QFile; + +namespace Phonon +{ + +class PHONON_EXPORT MediaSourcePrivate : public QSharedData +{ + public: + MediaSourcePrivate(MediaSource::Type t) + : type(t), discType(NoDisc), +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + stream(0), + ioDevice(0), +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + autoDelete(false) + { + } + + virtual ~MediaSourcePrivate(); + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + void setStream(AbstractMediaStream *s); +#endif + + MediaSource::Type type; + QUrl url; + Phonon::DiscType discType; + QString deviceName; + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + // The AbstractMediaStream(2) may be deleted at any time by the application. If that happens + // stream will be 0 automatically, but streamEventQueue will stay valid as we hold a + // reference to it. This is necessary to avoid a races when setting the MediaSource while + // another thread deletes the AbstractMediaStream2. StreamInterface(2) will then just get a + // StreamEventQueue where nobody answers. + QPointer<AbstractMediaStream> stream; + +// AudioCaptureDevice audioCaptureDevice; +// VideoCaptureDevice videoCaptureDevice; + QIODevice *ioDevice; +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + //QList<MediaSource> linkedSources; + bool autoDelete; +}; + +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // MEDIASOURCE_P_H +// vim: sw=4 sts=4 et tw=100 + + diff --git a/src/3rdparty/phonon/phonon/objectdescription.cpp b/src/3rdparty/phonon/phonon/objectdescription.cpp new file mode 100644 index 0000000..55e74b5 --- /dev/null +++ b/src/3rdparty/phonon/phonon/objectdescription.cpp @@ -0,0 +1,152 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "objectdescription.h" +#include "objectdescription_p.h" + +#include <QtCore/QObject> +#include <QtCore/QSet> +#include "factory_p.h" +#include <QtCore/QStringList> +#include "backendinterface.h" +#include "platformplugin.h" +#include "pulsesupport.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +ObjectDescriptionData::ObjectDescriptionData(int index, const QHash<QByteArray, QVariant> &properties) + : d(new ObjectDescriptionPrivate(index, properties)) +{ +} + +ObjectDescriptionData::ObjectDescriptionData(ObjectDescriptionPrivate *dd) + : d(dd) +{ +} + +ObjectDescriptionData::~ObjectDescriptionData() +{ + delete d; +} + +bool ObjectDescriptionData::operator==(const ObjectDescriptionData &otherDescription) const +{ + if (!isValid()) { + return !otherDescription.isValid(); + } + if (!otherDescription.isValid()) { + return false; + } + return *d == *otherDescription.d; +} + +int ObjectDescriptionData::index() const +{ + if (!isValid()) { + return -1; + } + return d->index; +} + +QString ObjectDescriptionData::name() const +{ + if (!isValid()) { + return QString(); + } + return d->name; +} + +QString ObjectDescriptionData::description() const +{ + if (!isValid()) { + return QString(); + } + return d->description; +} + +QVariant ObjectDescriptionData::property(const char *name) const +{ + if (!isValid()) { + return QVariant(); + } + return d->properties.value(name); +} + +QList<QByteArray> ObjectDescriptionData::propertyNames() const +{ + if (!isValid()) { + return QList<QByteArray>(); + } + return d->properties.keys(); +} + +bool ObjectDescriptionData::isValid() const +{ + return d != 0; +} + +ObjectDescriptionData *ObjectDescriptionData::fromIndex(ObjectDescriptionType type, int index) +{ + bool is_audio_device = (AudioOutputDeviceType == type || AudioCaptureDeviceType == type); + + PulseSupport *pulse = PulseSupport::getInstance(); + if (is_audio_device && pulse->isActive()) { + QList<int> indexes = pulse->objectDescriptionIndexes(type); + if (indexes.contains(index)) { + QHash<QByteArray, QVariant> properties = pulse->objectDescriptionProperties(type, index); + return new ObjectDescriptionData(index, properties); + } + } else { + BackendInterface *iface = qobject_cast<BackendInterface *>(Factory::backend()); + + // prefer to get the ObjectDescriptionData from the platform plugin for audio devices +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + if (is_audio_device) { + PlatformPlugin *platformPlugin = Factory::platformPlugin(); + if (platformPlugin) { + QList<int> indexes = platformPlugin->objectDescriptionIndexes(type); + if (indexes.contains(index)) { + QHash<QByteArray, QVariant> properties = platformPlugin->objectDescriptionProperties(type, index); + return new ObjectDescriptionData(index, properties); + } + } + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + + if (iface) { + QList<int> indexes = iface->objectDescriptionIndexes(type); + if (indexes.contains(index)) { + QHash<QByteArray, QVariant> properties = iface->objectDescriptionProperties(type, index); + return new ObjectDescriptionData(index, properties); + } + } + } + return new ObjectDescriptionData(0); // invalid +} + +} //namespace Phonon + +QT_END_NAMESPACE +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/objectdescription.h b/src/3rdparty/phonon/phonon/objectdescription.h new file mode 100644 index 0000000..985cdcc --- /dev/null +++ b/src/3rdparty/phonon/phonon/objectdescription.h @@ -0,0 +1,342 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_OBJECTDESCRIPTION_H +#define PHONON_OBJECTDESCRIPTION_H + +#include "phonon_export.h" + +#include <QtCore/QExplicitlySharedDataPointer> +#include <QtCore/QtDebug> +#include <QtCore/QList> +#include <QtCore/QSharedData> +#include <QtCore/QString> +#include <QtCore/QVariant> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class ObjectDescriptionPrivate; + + /** + * Defines the type of information that is contained in a ObjectDescription + * object. + * + * \ingroup Backend + */ + enum ObjectDescriptionType + { + /** + * Audio output devices. This can be soundcards (with different drivers), soundservers or + * other virtual outputs like playback on a different computer on the + * network. + * + * For Hardware devices the backend should use libkaudiodevicelist + * (AudioDevice and AudioDeviceEnumerator) which will list removable + * devices even when they are unplugged and provide a unique identifier + * that can make backends use the same identifiers. + */ + AudioOutputDeviceType, + + /** + * Lists all processing effects the backend supports. + */ + EffectType, + AudioChannelType, + SubtitleType, + + /** + * Audio capture devices. This can be soundcards (with different drivers), soundservers or + * other virtual inputs like capture on a different computer on the + * network. + * + * For Hardware devices the backend should use libkaudiodevicelist + * (AudioDevice and AudioDeviceEnumerator) which will list removable + * devices even when they are unplugged and provide a unique identifier + * that can make backends use the same identifiers. + */ + AudioCaptureDeviceType + + //VideoOutputDeviceType, + //VideoCaptureDeviceType, + //AudioCodecType, + //VideoCodecType, + //ContainerFormatType, + //VisualizationType, + }; + +/** \internal + * \class ObjectDescriptionData objectdescription.h Phonon/ObjectDescription + * \brief Data class for objects describing devices or features of the backend. + * + * \author Matthias Kretz <kretz@kde.org> + * \see BackendCapabilities + */ +class PHONON_EXPORT ObjectDescriptionData : public QSharedData //krazy:exclude=dpointer (it's protected, which should be fine for this type of class) +{ + public: + /** + * Returns \c true if this ObjectDescription describes the same + * as \p otherDescription; otherwise returns \c false. + */ + bool operator==(const ObjectDescriptionData &otherDescription) const; + + /** + * Returns the name of the capture source. + * + * \return A string that should be presented to the user to + * choose the capture source. + */ + QString name() const; + + /** + * Returns a description of the capture source. This text should + * make clear what sound source this is, which is sometimes hard + * to describe or understand from just the name. + * + * \return A string describing the capture source. + */ + QString description() const; + + /** + * Returns a named property. + * + * If the property is not set an invalid value is returned. + * + * \see propertyNames() + */ + QVariant property(const char *name) const; + + /** + * Returns all names that return valid data when property() is called. + * + * \see property() + */ + QList<QByteArray> propertyNames() const; + + /** + * Returns \c true if the Tuple is valid (index != -1); otherwise returns + * \c false. + */ + bool isValid() const; + + /** + * A unique identifier for this device/. Used internally + * to distinguish between the devices/. + * + * \return An integer that uniquely identifies every device/ + */ + int index() const; + + static ObjectDescriptionData *fromIndex(ObjectDescriptionType type, int index); + + ~ObjectDescriptionData(); + + ObjectDescriptionData(ObjectDescriptionPrivate * = 0); + ObjectDescriptionData(int index, const QHash<QByteArray, QVariant> &properties); + + protected: + ObjectDescriptionPrivate *const d; + + private: + ObjectDescriptionData &operator=(const ObjectDescriptionData &rhs); +}; + +template<ObjectDescriptionType T> class ObjectDescriptionModel; + +/** \class ObjectDescription objectdescription.h Phonon/ObjectDescription + * \short Provides a tuple of enduser visible name and description. + * + * Some parts give the enduser choices, e.g. what source to capture audio from. + * These choices are described by the name and description methods of this class + * and identified with the id method. Subclasses then define additional + * information like which audio and video choices belong together. + * + * \ingroup Frontend + * \author Matthias Kretz <kretz@kde.org> + */ +template<ObjectDescriptionType T> +class ObjectDescription +{ + public: + /** + * Returns a new description object that describes the + * device/effect/codec/... with the given \p index. + */ + static inline ObjectDescription<T> fromIndex(int index) { //krazy:exclude=inline + return ObjectDescription<T>(QExplicitlySharedDataPointer<ObjectDescriptionData>(ObjectDescriptionData::fromIndex(T, index))); + } + + /** + * Returns \c true if this ObjectDescription describes the same + * as \p otherDescription; otherwise returns \c false. + */ + inline bool operator==(const ObjectDescription &otherDescription) const { //krazy:exclude=inline + return *d == *otherDescription.d; + } + + /** + * Returns \c false if this ObjectDescription describes the same + * as \p otherDescription; otherwise returns \c true. + */ + inline bool operator!=(const ObjectDescription &otherDescription) const { //krazy:exclude=inline + return !operator==(otherDescription); + } + + /** + * Returns the name of the capture source. + * + * \return A string that should be presented to the user to + * choose the capture source. + */ + inline QString name() const { return d->name(); } //krazy:exclude=inline + + /** + * Returns a description of the capture source. This text should + * make clear what sound source this is, which is sometimes hard + * to describe or understand from just the name. + * + * \return A string describing the capture source. + */ + inline QString description() const { return d->description(); } //krazy:exclude=inline + + /** + * Returns a named property. + * + * If the property is not set an invalid value is returned. + * + * \see propertyNames() + */ + inline QVariant property(const char *name) const { return d->property(name); } //krazy:exclude=inline + + /** + * Returns all names that return valid data when property() is called. + * + * \see property() + */ + inline QList<QByteArray> propertyNames() const { return d->propertyNames(); } //krazy:exclude=inline + + /** + * Returns \c true if the Tuple is valid (index != -1); otherwise returns + * \c false. + */ + inline bool isValid() const { return d->isValid(); } //krazy:exclude=inline + + /** + * A unique identifier for this device/. Used internally + * to distinguish between the devices/. + * + * \return An integer that uniquely identifies every device/ + */ + inline int index() const { return d->index(); } //krazy:exclude=inline + + ObjectDescription() : d(new ObjectDescriptionData(0)) {} + ObjectDescription(int index, const QHash<QByteArray, QVariant> &properties) : d(new ObjectDescriptionData(index, properties)) {} + + protected: + friend class ObjectDescriptionModel<T>; + ObjectDescription(const QExplicitlySharedDataPointer<ObjectDescriptionData> &dd) : d(dd) {} + QExplicitlySharedDataPointer<ObjectDescriptionData> d; +}; + +template<ObjectDescriptionType T> +inline QDebug operator<<(QDebug s, const ObjectDescription<T> &o) //krazy:exclude=inline +{ + return s << o.name(); +} + +/** + * \ingroup BackendInformation + */ +typedef ObjectDescription<AudioOutputDeviceType> AudioOutputDevice; +/** + * \ingroup BackendInformation + */ +#ifndef QT_NO_PHONON_AUDIOCAPTURE +typedef ObjectDescription<AudioCaptureDeviceType> AudioCaptureDevice; +#endif //QT_NO_PHONON_AUDIOCAPTURE +/** + * \ingroup BackendInformation + */ +//typedef ObjectDescription<VideoOutputDeviceType> VideoOutputDevice; +/** + * \ingroup BackendInformation + */ +//typedef ObjectDescription<VideoCaptureDeviceType> VideoCaptureDevice; +/** + * \ingroup BackendInformation + */ +#ifndef QT_NO_PHONON_EFFECT +typedef ObjectDescription<EffectType> EffectDescription; +#endif //QT_NO_PHONON_EFFECT + +/** + * \ingroup BackendInformation + */ +//typedef ObjectDescription<AudioCodecType> AudioCodecDescription; +/** + * \ingroup BackendInformation + */ +//typedef ObjectDescription<VideoCodecType> VideoCodecDescription; +/** + * \ingroup BackendInformation + */ +//typedef ObjectDescription<ContainerFormatType> ContainerFormatDescription; +/** + * \ingroup BackendInformation + */ +//typedef ObjectDescription<VisualizationType> VisualizationDescription; +#ifndef QT_NO_PHONON_MEDIACONTROLLER +typedef ObjectDescription<AudioChannelType> AudioChannelDescription; +typedef ObjectDescription<SubtitleType> SubtitleDescription; +#endif //QT_NO_PHONON_MEDIACONTROLLER + +} //namespace Phonon + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Phonon::AudioOutputDevice) +Q_DECLARE_METATYPE(QList<Phonon::AudioOutputDevice>) + +#ifndef QT_NO_PHONON_AUDIOCAPTURE +Q_DECLARE_METATYPE(Phonon::AudioCaptureDevice) +Q_DECLARE_METATYPE(QList<Phonon::AudioCaptureDevice>) +#endif //QT_NO_PHONON_AUDIOCAPTURE + +#ifndef QT_NO_PHONON_EFFECT +Q_DECLARE_METATYPE(QList<Phonon::EffectDescription>) +Q_DECLARE_METATYPE(Phonon::EffectDescription) +#endif //QT_NO_PHONON_EFFECT + + +#ifndef QT_NO_PHONON_MEDIACONTROLLER +Q_DECLARE_METATYPE(Phonon::AudioChannelDescription) +Q_DECLARE_METATYPE(Phonon::SubtitleDescription) +Q_DECLARE_METATYPE(QList<Phonon::AudioChannelDescription>) +Q_DECLARE_METATYPE(QList<Phonon::SubtitleDescription>) +#endif //QT_NO_PHONON_MEDIACONTROLLER + +QT_END_HEADER + +#endif // PHONON_OBJECTDESCRIPTION_H diff --git a/src/3rdparty/phonon/phonon/objectdescription_p.h b/src/3rdparty/phonon/phonon/objectdescription_p.h new file mode 100644 index 0000000..bcf56de --- /dev/null +++ b/src/3rdparty/phonon/phonon/objectdescription_p.h @@ -0,0 +1,64 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_OBJECTDESCRIPTION_P_H +#define PHONON_OBJECTDESCRIPTION_P_H + +#include <QtCore/QByteRef> +#include <QtCore/QHash> +#include <QtCore/QString> +#include <QtCore/QVariant> +#include "phononnamespace_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class ObjectDescriptionPrivate + { + public: + ObjectDescriptionPrivate(int _index, const QHash<QByteArray, QVariant> &_properties) + : index(_index), + name(_properties["name"].toString()), + description(_properties["description"].toString()), + properties(_properties) + { + } + + bool operator==(const ObjectDescriptionPrivate &rhs) const + { + if (index == rhs.index && (name != rhs.name || description != rhs.description)) + pError() << "Same index (" << index << + "), but different name/description. This is a bug in the Phonon backend."; + return index == rhs.index;// && name == rhs.name && description == rhs.description; + } + + int index; + QString name, description; + QHash<QByteArray, QVariant> properties; + }; +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // PHONON_OBJECTDESCRIPTION_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp new file mode 100644 index 0000000..741a74c --- /dev/null +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp @@ -0,0 +1,387 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "objectdescriptionmodel.h" +#include "objectdescriptionmodel_p.h" +#include "phonondefs_p.h" +#include "platform_p.h" +#include <QtCore/QList> +#include "objectdescription.h" +#include "phononnamespace_p.h" +#include <QtCore/QMimeData> +#include <QtCore/QStringList> +#include <QtGui/QIcon> +#include "factory_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL + + +static const uint qt_meta_data_Phonon__ObjectDescriptionModel[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + + 0 // eod +}; + +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioOutputDeviceType[] = { "Phonon::AudioOutputDevice\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCaptureDeviceType[] = { "Phonon::AudioCaptureDevice\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_EffectType[] = { "Phonon::EffectDescription\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioChannelType[] = { "Phonon::AudioChannelDescription\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_SubtitleType[] = { "Phonon::SubtitleDescription\0" }; +/* +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoOutputDeviceType[] = { "Phonon::VideoOutputDevice\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCaptureDeviceType[] = { "Phonon::VideoCaptureDevice\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCodecType[] = { "Phonon::AudioCodecDescription\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCodecType[] = { "Phonon::VideoCodecDescription\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_ContainerFormatType[] = { "Phonon::ContainerFormatDescription\0" }; +static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VisualizationType[] = { "Phonon::VisualizationDescription\0" }; +*/ + +namespace Phonon +{ + +template<> const QMetaObject ObjectDescriptionModel<AudioOutputDeviceType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioOutputDeviceType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<EffectType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_EffectType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<AudioChannelType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioChannelType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<SubtitleType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_SubtitleType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<AudioCaptureDeviceType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCaptureDeviceType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +/*template<> const QMetaObject ObjectDescriptionModel<VideoOutputDeviceType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoOutputDeviceType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<VideoCaptureDeviceType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCaptureDeviceType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<AudioCodecType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCodecType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<VideoCodecType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCodecType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<ContainerFormatType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_ContainerFormatType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +}; +template<> const QMetaObject ObjectDescriptionModel<VisualizationType>::staticMetaObject = { + { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VisualizationType, + qt_meta_data_Phonon__ObjectDescriptionModel, 0 } +};*/ + +template<ObjectDescriptionType type> +const QMetaObject *ObjectDescriptionModel<type>::metaObject() const +{ + return &staticMetaObject; +} + +template<ObjectDescriptionType type> +void *ObjectDescriptionModel<type>::qt_metacast(const char *_clname) +{ + if (!_clname) { + return 0; + } + if (!strcmp(_clname, ObjectDescriptionModel<type>::staticMetaObject.className())) { + return static_cast<void *>(const_cast<ObjectDescriptionModel<type> *>(this)); + } + return QAbstractListModel::qt_metacast(_clname); +} + +/* +template<ObjectDescriptionType type> +int ObjectDescriptionModel<type>::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + return QAbstractListModel::qt_metacall(_c, _id, _a); +} +*/ + +int ObjectDescriptionModelData::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + return d->data.size(); +} + +QVariant ObjectDescriptionModelData::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= d->data.size() || index.column() != 0) + return QVariant(); + + switch(role) + { + case Qt::EditRole: + case Qt::DisplayRole: + return d->data.at(index.row())->name(); + break; + case Qt::ToolTipRole: + return d->data.at(index.row())->description(); + break; + case Qt::DecorationRole: + { + QVariant icon = d->data.at(index.row())->property("icon"); + if (icon.isValid()) { + if (icon.type() == QVariant::String) { + return Platform::icon(icon.toString()); + } else if (icon.type() == QVariant::Icon) { + return icon; + } + } + } + return QVariant(); + default: + return QVariant(); +} +} + +Qt::ItemFlags ObjectDescriptionModelData::flags(const QModelIndex &index) const +{ + if(!index.isValid() || index.row() >= d->data.size() || index.column() != 0) { + return Qt::ItemIsDropEnabled; + } + + QVariant available = d->data.at(index.row())->property("available"); + if (available.isValid() && available.type() == QVariant::Bool && !available.toBool()) { + return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; + } + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled; +} + +QList<int> ObjectDescriptionModelData::tupleIndexOrder() const +{ + QList<int> ret; + for (int i = 0; i < d->data.size(); ++i) { + ret.append(d->data.at(i)->index()); + } + return ret; +} + +int ObjectDescriptionModelData::tupleIndexAtPositionIndex(int positionIndex) const +{ + return d->data.at(positionIndex)->index(); +} + +QMimeData *ObjectDescriptionModelData::mimeData(ObjectDescriptionType type, const QModelIndexList &indexes) const +{ + QMimeData *mimeData = new QMimeData; + QByteArray encodedData; + QDataStream stream(&encodedData, QIODevice::WriteOnly); + QModelIndexList::const_iterator end = indexes.constEnd(); + QModelIndexList::const_iterator index = indexes.constBegin(); + for(; index!=end; ++index) { + if ((*index).isValid()) { + stream << d->data.at((*index).row())->index(); + } + } + //pDebug() << Q_FUNC_INFO << "setting mimeData to" << mimeTypes(type).first() << "=>" << encodedData.toHex(); + mimeData->setData(mimeTypes(type).first(), encodedData); + return mimeData; +} + +void ObjectDescriptionModelData::moveUp(const QModelIndex &index) +{ + if (!index.isValid() || index.row() >= d->data.size() || index.row() < 1 || index.column() != 0) + return; + + emit d->model->layoutAboutToBeChanged(); + QModelIndex above = index.sibling(index.row() - 1, index.column()); + d->data.swap(index.row(), above.row()); + QModelIndexList from, to; + from << index << above; + to << above << index; + d->model->changePersistentIndexList(from, to); + emit d->model->layoutChanged(); +} + +void ObjectDescriptionModelData::moveDown(const QModelIndex &index) +{ + if (!index.isValid() || index.row() >= d->data.size() - 1 || index.column() != 0) + return; + + emit d->model->layoutAboutToBeChanged(); + QModelIndex below = index.sibling(index.row() + 1, index.column()); + d->data.swap(index.row(), below.row()); + QModelIndexList from, to; + from << index << below; + to << below << index; + d->model->changePersistentIndexList(from, to); + emit d->model->layoutChanged(); +} + +ObjectDescriptionModelData::ObjectDescriptionModelData(QAbstractListModel *model) + : d(new ObjectDescriptionModelDataPrivate(model)) +{ +} + +ObjectDescriptionModelData::~ObjectDescriptionModelData() +{ + delete d; +} + +void ObjectDescriptionModelData::setModelData(const QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > &newData) +{ + d->data = newData; + d->model->reset(); +} + +QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > ObjectDescriptionModelData::modelData() const +{ + return d->data; +} + +QExplicitlySharedDataPointer<ObjectDescriptionData> ObjectDescriptionModelData::modelData(const QModelIndex &index) const +{ + if (!index.isValid() || index.row() >= d->data.size() || index.column() != 0) { + return QExplicitlySharedDataPointer<ObjectDescriptionData>(new ObjectDescriptionData(0)); + } + return d->data.at(index.row()); +} + +Qt::DropActions ObjectDescriptionModelData::supportedDropActions() const +{ + //pDebug() << Q_FUNC_INFO; + return Qt::MoveAction; +} + +bool ObjectDescriptionModelData::dropMimeData(ObjectDescriptionType type, const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + Q_UNUSED(action); + Q_UNUSED(column); + Q_UNUSED(parent); + //pDebug() << Q_FUNC_INFO << data << action << row << column << parent; + + QString format = mimeTypes(type).first(); + if (!data->hasFormat(format)) { + return false; + } + + if (row == -1) { + row = d->data.size(); + } + + QByteArray encodedData = data->data(format); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > toInsert; + while (!stream.atEnd()) { + int otherIndex; + stream >> otherIndex; + ObjectDescriptionData *obj = ObjectDescriptionData::fromIndex(type, otherIndex); + + if (obj->isValid()) { + toInsert << QExplicitlySharedDataPointer<ObjectDescriptionData>(obj); + } else { + delete obj; + } + } + d->model->beginInsertRows(QModelIndex(), row, row + toInsert.size() - 1); + for (int i = 0 ; i < toInsert.count(); ++i) { + d->data.insert(row, toInsert.at(i)); + } + d->model->endInsertRows(); + return true; +} + + +bool ObjectDescriptionModelData::removeRows(int row, int count, const QModelIndex &parent) +{ + //pDebug() << Q_FUNC_INFO << row << count << parent; + if (parent.isValid() || row + count > d->data.size()) { + return false; + } + d->model->beginRemoveRows(parent, row, row + count - 1); + for (;count > 0; --count) { + d->data.removeAt(row); + } + d->model->endRemoveRows(); + return true; +} + +/* +template<ObjectDescriptionType type> +bool ObjectDescriptionModel<type>::insertRows(int row, int count, const QModelIndex &parent) +{ + pDebug() << Q_FUNC_INFO << row << count << parent; + if (parent.isValid() || row < 0 || row > d->data.size()) { + return false; + } + beginInsertRows(parent, row, row + count - 1); + for (;count > 0; --count) { + d->data.insert(row, ObjectDescription<type>()); + } + endInsertRows(); + return true; +} +*/ + +QStringList ObjectDescriptionModelData::mimeTypes(ObjectDescriptionType type) const +{ + return QStringList(QLatin1String("application/x-phonon-objectdescription") + QString::number(static_cast<int>(type))); +} + +#if !defined(Q_CC_MSVC) || _MSC_VER > 1300 || defined(Q_CC_INTEL) || defined(Q_CC_MINGW) +#define INSTANTIATE_META_FUNCTIONS(type) \ +template const QMetaObject *ObjectDescriptionModel<type>::metaObject() const; \ +template void *ObjectDescriptionModel<type>::qt_metacast(const char *) + +INSTANTIATE_META_FUNCTIONS(AudioOutputDeviceType); +INSTANTIATE_META_FUNCTIONS(AudioCaptureDeviceType); +INSTANTIATE_META_FUNCTIONS(EffectType); +INSTANTIATE_META_FUNCTIONS(AudioChannelType); +INSTANTIATE_META_FUNCTIONS(SubtitleType); +#endif +/*INSTANTIATE_META_FUNCTIONS(VideoOutputDeviceType); +INSTANTIATE_META_FUNCTIONS(VideoCaptureDeviceType); +INSTANTIATE_META_FUNCTIONS(AudioCodecType); +INSTANTIATE_META_FUNCTIONS(VideoCodecType); +INSTANTIATE_META_FUNCTIONS(ContainerFormatType); +INSTANTIATE_META_FUNCTIONS(VisualizationType); +*/ +} // namespace Phonon + +#endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h new file mode 100644 index 0000000..d994600 --- /dev/null +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h @@ -0,0 +1,388 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_OBJECTDESCRIPTIONMODEL_H +#define PHONON_OBJECTDESCRIPTIONMODEL_H + +#include "phonon_export.h" +#include "phonondefs.h" +#include "objectdescription.h" +#include <QtCore/QList> +#include <QtCore/QModelIndex> +#include <QtCore/QStringList> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL + +namespace Phonon +{ + class ObjectDescriptionModelDataPrivate; + + /** \internal + * \class ObjectDescriptionModelData objectdescriptionmodel.h Phonon/ObjectDescriptionModelData + * \brief Data class for models for ObjectDescription objects. + * + * \author Matthias Kretz <kretz@kde.org> + */ + class PHONON_EXPORT ObjectDescriptionModelData + { + public: + /** + * Returns the number of rows in the model. This value corresponds + * to the size of the list passed through setModelData. + * + * \param parent The optional \p parent argument is used in most models to specify + * the parent of the rows to be counted. Because this is a list if a + * valid parent is specified the result will always be 0. + * + * Reimplemented from QAbstractItemModel. + * + * \see QAbstractItemModel::rowCount + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + /** + * Returns data from the item with the given \p index for the specified + * \p role. + * If the view requests an invalid index, an invalid variant is + * returned. + * + * Reimplemented from QAbstractItemModel. + * + * \see QAbstractItemModel::data + * \see Qt::ItemDataRole + */ + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + /** + * Reimplemented to show unavailable devices as disabled (but still + * selectable). + */ + Qt::ItemFlags flags(const QModelIndex &index) const; + + /** + * Returns a list of indexes in the same order as they are in the + * model. The indexes come from the ObjectDescription::index + * method. + * + * This is useful to let the user define a list of preference. + */ + QList<int> tupleIndexOrder() const; + + /** + * Returns the ObjectDescription::index for the tuple + * at the given position \p positionIndex. For example a + * QComboBox will give you the currentIndex as the + * position in the list. But to select the according + * AudioOutputDevice using AudioOutputDevice::fromIndex + * you can use this method. + * + * \param positionIndex The position in the list. + */ + int tupleIndexAtPositionIndex(int positionIndex) const; + + /** + * Returns the MIME data that dropMimeData() can use to create new + * items. + */ + QMimeData *mimeData(ObjectDescriptionType type, const QModelIndexList &indexes) const; + + /** + * Moves the item at the given \p index up. In the resulting list + * the items at index.row() and index.row() - 1 are swapped. + * + * Connected views are updated automatically. + */ + void moveUp(const QModelIndex &index); + + /** + * Moves the item at the given \p index down. In the resulting list + * the items at index.row() and index.row() + 1 are swapped. + * + * Connected views are updated automatically. + */ + void moveDown(const QModelIndex &index); + + void setModelData(const QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > &data); + QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > modelData() const; + QExplicitlySharedDataPointer<ObjectDescriptionData> modelData(const QModelIndex &index) const; + Qt::DropActions supportedDropActions() const; + bool dropMimeData(ObjectDescriptionType type, const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + QStringList mimeTypes(ObjectDescriptionType type) const; + + ObjectDescriptionModelData(QAbstractListModel *); + protected: + ~ObjectDescriptionModelData(); + //ObjectDescriptionModelData(ObjectDescriptionModelDataPrivate *dd); + ObjectDescriptionModelDataPrivate *const d; + }; + +/* Required to ensure template class vtables are exported on both symbian +and existing builds. */ +#if (defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)) || defined(Q_CC_CLANG) +// RVCT compiler (2.2.686) requires the export declaration to be on the class to export vtables +// MWC compiler works both ways +// GCCE compiler is unknown (it can't compile QtCore yet) +// Clang also requires the export declaration to be on the class to export vtables +#define PHONON_TEMPLATE_CLASS_EXPORT PHONON_EXPORT +#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT +#else +// Windows builds (at least) do not support export declaration on templated class +// But if you export a member function, the vtable is implicitly exported +#define PHONON_TEMPLATE_CLASS_EXPORT +#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT PHONON_EXPORT +#endif + + /** \class ObjectDescriptionModel objectdescriptionmodel.h Phonon/ObjectDescriptionModel + * \short The ObjectDescriptionModel class provides a model from + * a list of ObjectDescription objects. + * + * ObjectDescriptionModel is a readonly model that supplies a list + * using ObjectDescription::name() for the text and + * ObjectDescription::description() for the tooltip. If set the properties + * "icon" and "available" are used to set the decoration and disable the + * item (disabled only visually, you can still select and drag it). + * + * It also provides the methods moveUp() and moveDown() to order the list. + * Additionally drag and drop is possible so that + * QAbstractItemView::InternalMove can be used. + * The resulting order of the ObjectDescription::index() values can then be + * retrieved using tupleIndexOrder(). + * + * An example use case would be to give the user a QComboBox to select + * the output device: + * \code + * QComboBox *cb = new QComboBox(parentWidget); + * ObjectDescriptionModel *model = new ObjectDescriptionModel(cb); + * model->setModelData(BackendCapabilities::availableAudioOutputDevices()); + * cb->setModel(model); + * cb->setCurrentIndex(0); // select first entry + * \endcode + * + * And to retrieve the selected AudioOutputDevice: + * \code + * int cbIndex = cb->currentIndex(); + * AudioOutputDevice selectedDevice = model->modelData(cbIndex); + * \endcode + * + * \ingroup Frontend + * \author Matthias Kretz <kretz@kde.org> + */ + template<ObjectDescriptionType type> + class PHONON_TEMPLATE_CLASS_EXPORT ObjectDescriptionModel : public QAbstractListModel + { + public: + Q_OBJECT_CHECK + + /** \internal */ + static PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject staticMetaObject; + /** \internal */ + PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject *metaObject() const; + /** \internal */ + PHONON_TEMPLATE_CLASS_MEMBER_EXPORT void *qt_metacast(const char *_clname); + //int qt_metacall(QMetaObject::Call _c, int _id, void **_a); + + /** + * Returns the number of rows in the model. This value corresponds + * to the size of the list passed through setModelData. + * + * \param parent The optional \p parent argument is used in most models to specify + * the parent of the rows to be counted. Because this is a list if a + * valid parent is specified the result will always be 0. + * + * Reimplemented from QAbstractItemModel. + * + * \see QAbstractItemModel::rowCount + */ + inline int rowCount(const QModelIndex &parent = QModelIndex()) const { return d->rowCount(parent); } //krazy:exclude=inline + + /** + * Returns data from the item with the given \p index for the specified + * \p role. + * If the view requests an invalid index, an invalid variant is + * returned. + * + * Reimplemented from QAbstractItemModel. + * + * \see QAbstractItemModel::data + * \see Qt::ItemDataRole + */ + inline QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const { return d->data(index, role); } //krazy:exclude=inline + + /** + * Reimplemented to show unavailable devices as disabled (but still + * selectable). + */ + inline Qt::ItemFlags flags(const QModelIndex &index) const { return d->flags(index); } //krazy:exclude=inline + + /** + * Returns a list of indexes in the same order as they are in the + * model. The indexes come from the ObjectDescription::index + * method. + * + * This is useful to let the user define a list of preference. + */ + inline QList<int> tupleIndexOrder() const { return d->tupleIndexOrder(); } //krazy:exclude=inline + + /** + * Returns the ObjectDescription::index for the tuple + * at the given position \p positionIndex. For example a + * QComboBox will give you the currentIndex as the + * position in the list. But to select the according + * AudioOutputDevice using AudioOutputDevice::fromIndex + * you can use this method. + * + * \param positionIndex The position in the list. + */ + inline int tupleIndexAtPositionIndex(int positionIndex) const { return d->tupleIndexAtPositionIndex(positionIndex); } //krazy:exclude=inline + + /** + * Returns the MIME data that dropMimeData() can use to create new + * items. + */ + inline QMimeData *mimeData(const QModelIndexList &indexes) const { return d->mimeData(type, indexes); } //krazy:exclude=inline + + /** + * Moves the item at the given \p index up. In the resulting list + * the items at index.row() and index.row() - 1 are swapped. + * + * Connected views are updated automatically. + */ + inline void moveUp(const QModelIndex &index) { d->moveUp(index); } //krazy:exclude=inline + + /** + * Moves the item at the given \p index down. In the resulting list + * the items at index.row() and index.row() + 1 are swapped. + * + * Connected views are updated automatically. + */ + inline void moveDown(const QModelIndex &index) { d->moveDown(index); } //krazy:exclude=inline + + /** + * Constructs a ObjectDescription model with the + * given \p parent. + */ + explicit inline ObjectDescriptionModel(QObject *parent = 0) : QAbstractListModel(parent), d(new ObjectDescriptionModelData(this)) {} //krazy:exclude=inline + + /** + * Constructs a ObjectDescription model with the + * given \p parent and the given \p data. + */ + explicit inline ObjectDescriptionModel(const QList<ObjectDescription<type> > &data, QObject *parent = 0) //krazy:exclude=inline + : QAbstractListModel(parent), d(new ObjectDescriptionModelData(this)) { setModelData(data); } + + /** + * Sets the model data using the list provided by \p data. + * + * All previous model data is cleared. + */ + inline void setModelData(const QList<ObjectDescription<type> > &data) { //krazy:exclude=inline + QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > list; + for (int i = 0; i < data.count(); ++i) { + list += data.at(i).d; + } + d->setModelData(list); + } + + /** + * Returns the model data. + * + * As the order of the list might have changed this can be different + * to what was set using setModelData(). + */ + inline QList<ObjectDescription<type> > modelData() const { //krazy:exclude=inline + QList<ObjectDescription<type> > ret; + QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > list = d->modelData(); + for (int i = 0; i < list.count(); ++i) { + ret << ObjectDescription<type>(list.at(i)); + } + return ret; + } + + /** + * Returns one ObjectDescription of the model data for the given \p index. + */ + inline ObjectDescription<type> modelData(const QModelIndex &index) const { return ObjectDescription<type>(d->modelData(index)); } //krazy:exclude=inline + + /** + * This model supports drag and drop to copy or move + * items. + */ + inline Qt::DropActions supportedDropActions() const { return d->supportedDropActions(); } //krazy:exclude=inline + + /** + * Accept drops from other models of the same ObjectDescriptionType. + * + * If a valid \p parent is given the dropped items will be inserted + * above that item. + */ + inline bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { //krazy:exclude=inline + return d->dropMimeData(type, data, action, row, column, parent); + } + + /** + * Removes count rows starting with the given row. + * + * If a valid \p parent is given no rows are removed since this is a + * list model. + * + * Returns true if the rows were successfully removed; otherwise returns false. + */ + inline bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) { //krazy:exclude=inline + return d->removeRows(row, count, parent); + } + + /** + * Returns a list of supported drag and drop MIME types. Currently + * it only supports one type used internally. + */ + inline QStringList mimeTypes() const { return d->mimeTypes(type); } //krazy:exclude=inline + + protected: + ObjectDescriptionModelData *const d; + }; + + typedef ObjectDescriptionModel<AudioOutputDeviceType> AudioOutputDeviceModel; + typedef ObjectDescriptionModel<AudioCaptureDeviceType> AudioCaptureDeviceModel; + typedef ObjectDescriptionModel<EffectType> EffectDescriptionModel; + typedef ObjectDescriptionModel<AudioChannelType> AudioChannelDescriptionModel; + typedef ObjectDescriptionModel<SubtitleType> SubtitleDescriptionModel; +/* + typedef ObjectDescriptionModel<VideoOutputDeviceType> VideoOutputDeviceModel; + typedef ObjectDescriptionModel<VideoCaptureDeviceType> VideoCaptureDeviceModel; + typedef ObjectDescriptionModel<AudioCodecType> AudioCodecDescriptionModel; + typedef ObjectDescriptionModel<VideoCodecType> VideoCodecDescriptionModel; + typedef ObjectDescriptionModel<ContainerFormatType> ContainerFormatDescriptionModel; + typedef ObjectDescriptionModel<VisualizationType> VisualizationDescriptionModel;*/ + +} + +#endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_OBJECTDESCRIPTIONMODEL_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h new file mode 100644 index 0000000..2200c8d --- /dev/null +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h @@ -0,0 +1,65 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_OBJECTDESCRIPTIONMODEL_P_H +#define PHONON_OBJECTDESCRIPTIONMODEL_P_H + +#include "objectdescriptionmodel.h" +#include <QtCore/QList> +#include "objectdescription.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL + +namespace Phonon +{ + +class ListModelHelper : public QAbstractListModel +{ + public: + using QAbstractListModel::layoutAboutToBeChanged; + using QAbstractListModel::changePersistentIndexList; + using QAbstractListModel::layoutChanged; + using QAbstractListModel::reset; + using QAbstractListModel::beginInsertRows; + using QAbstractListModel::endInsertRows; + using QAbstractListModel::beginRemoveRows; + using QAbstractListModel::endRemoveRows; +}; + +class ObjectDescriptionModelDataPrivate +{ + public: + ObjectDescriptionModelDataPrivate(QAbstractListModel *m) : model(reinterpret_cast<ListModelHelper *>(m)) {} + QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > data; + ListModelHelper *model; +}; + +} + +#endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL + +QT_END_NAMESPACE + +#endif // PHONON_OBJECTDESCRIPTIONMODEL_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml b/src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml new file mode 100644 index 0000000..2498337 --- /dev/null +++ b/src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml @@ -0,0 +1,32 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.kde.Phonon.AudioOutput"> + <property name="volume" type="d" access="readwrite"/> + <property name="muted" type="b" access="readwrite"/> + <property name="outputDeviceIndex" type="i" access="readwrite"/> + <signal name="volumeChanged"> + <arg type="d" direction="out"/> + </signal> + <signal name="mutedChanged"> + <arg type="b" direction="out"/> + </signal> + <signal name="outputDeviceIndexChanged"> + <arg type="i" direction="out"/> + </signal> + <signal name="nameChanged"> + <arg name="newName" type="s" direction="out"/> + </signal> + <signal name="newOutputAvailable"> + <arg name="service" type="s" direction="out"/> + <arg name="path" type="s" direction="out"/> + </signal> + <signal name="outputDestroyed"> + </signal> + <method name="category"> + <arg type="s" direction="out"/> + </method> + <method name="name"> + <arg type="s" direction="out"/> + </method> + </interface> +</node> diff --git a/src/3rdparty/phonon/phonon/path.cpp b/src/3rdparty/phonon/phonon/path.cpp new file mode 100644 index 0000000..1c25b89 --- /dev/null +++ b/src/3rdparty/phonon/phonon/path.cpp @@ -0,0 +1,476 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "path.h" +#include "path_p.h" + +#include "phononnamespace_p.h" +#include "backendinterface.h" +#include "factory_p.h" +#include "medianode.h" +#include "medianode_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +class ConnectionTransaction +{ + public: + ConnectionTransaction(BackendInterface *b, const QSet<QObject*> &x) : backend(b), list(x) + { + success = backend->startConnectionChange(list); + } + ~ConnectionTransaction() + { + backend->endConnectionChange(list); + } + operator bool() + { + return success; + } + private: + bool success; + BackendInterface *const backend; + const QSet<QObject*> list; +}; + +PathPrivate::~PathPrivate() +{ +#ifndef QT_NO_PHONON_EFFECT + for (int i = 0; i < effects.count(); ++i) { + effects.at(i)->k_ptr->removeDestructionHandler(this); + } + delete effectsParent; +#endif +} + +Path::~Path() +{ +} + +Path::Path() + : d(new PathPrivate) +{ +} + +Path::Path(const Path &rhs) + : d(rhs.d) +{ +} + +bool Path::isValid() const +{ + return d->sourceNode != 0 && d->sinkNode != 0; +} + +#ifndef QT_NO_PHONON_EFFECT +Effect *Path::insertEffect(const EffectDescription &desc, Effect *insertBefore) +{ + if (!d->effectsParent) { + d->effectsParent = new QObject; + } + Effect *e = new Effect(desc, d->effectsParent); + if (!e->isValid()) { + delete e; + return 0; + } + bool success = insertEffect(e, insertBefore); + if (!success) { + delete e; + return 0; + } + return e; +} + +bool Path::insertEffect(Effect *newEffect, Effect *insertBefore) +{ + QObject *newEffectBackend = newEffect ? newEffect->k_ptr->backendObject() : 0; + if (!isValid() || !newEffectBackend || d->effects.contains(newEffect) || + (insertBefore && (!d->effects.contains(insertBefore) || !insertBefore->k_ptr->backendObject()))) { + return false; + } + QObject *leftNode = 0; + QObject *rightNode = 0; + const int insertIndex = insertBefore ? d->effects.indexOf(insertBefore) : d->effects.size(); + if (insertIndex == 0) { + //prepend + leftNode = d->sourceNode->k_ptr->backendObject(); + } else { + leftNode = d->effects[insertIndex - 1]->k_ptr->backendObject(); + } + + if (insertIndex == d->effects.size()) { + //append + rightNode = d->sinkNode->k_ptr->backendObject(); + } else { + Q_ASSERT(insertBefore); + rightNode = insertBefore->k_ptr->backendObject(); + } + + QList<QObjectPair> disconnections, connections; + disconnections << QObjectPair(leftNode, rightNode); + connections << QObjectPair(leftNode, newEffectBackend) + << QObjectPair(newEffectBackend, rightNode); + + if (d->executeTransaction(disconnections, connections)) { + newEffect->k_ptr->addDestructionHandler(d.data()); + d->effects.insert(insertIndex, newEffect); + return true; + } else { + return false; + } +} + +bool Path::removeEffect(Effect *effect) +{ + return d->removeEffect(effect); +} + +QList<Effect *> Path::effects() const +{ + return d->effects; +} +#endif //QT_NO_PHONON_EFFECT + +bool Path::reconnect(MediaNode *source, MediaNode *sink) +{ + if (!source || !sink || !source->k_ptr->backendObject() || !sink->k_ptr->backendObject()) { + return false; + } + + QList<QObjectPair> disconnections, connections; + + //backend objects + QObject *bnewSource = source->k_ptr->backendObject(); + QObject *bnewSink = sink->k_ptr->backendObject(); + QObject *bcurrentSource = d->sourceNode ? d->sourceNode->k_ptr->backendObject() : 0; + QObject *bcurrentSink = d->sinkNode ? d->sinkNode->k_ptr->backendObject() : 0; + + if (bnewSource != bcurrentSource) { + //we need to change the source +#ifndef QT_NO_PHONON_EFFECT + MediaNode *next = d->effects.isEmpty() ? sink : d->effects.first(); +#else + MediaNode *next = sink; +#endif //QT_NO_PHONON_EFFECT + QObject *bnext = next->k_ptr->backendObject(); + if (bcurrentSource) + disconnections << QObjectPair(bcurrentSource, bnext); + connections << QObjectPair(bnewSource, bnext); + } + + if (bnewSink != bcurrentSink) { +#ifndef QT_NO_PHONON_EFFECT + MediaNode *previous = d->effects.isEmpty() ? source : d->effects.last(); +#else + MediaNode *previous = source; +#endif //QT_NO_PHONON_EFFECT + QObject *bprevious = previous->k_ptr->backendObject(); + if (bcurrentSink) + disconnections << QObjectPair(bprevious, bcurrentSink); + QObjectPair pair(bprevious, bnewSink); + if (!connections.contains(pair)) //avoid connecting twice + connections << pair; + } + + if (d->executeTransaction(disconnections, connections)) { + + //everything went well: let's update the path and the sink node + if (d->sinkNode != sink) { + if (d->sinkNode) { + d->sinkNode->k_ptr->removeInputPath(*this); + d->sinkNode->k_ptr->removeDestructionHandler(d.data()); + } + sink->k_ptr->addInputPath(*this); + d->sinkNode = sink; + d->sinkNode->k_ptr->addDestructionHandler(d.data()); + } + + //everything went well: let's update the path and the source node + if (d->sourceNode != source) { + source->k_ptr->addOutputPath(*this); + if (d->sourceNode) { + d->sourceNode->k_ptr->removeOutputPath(*this); + d->sourceNode->k_ptr->removeDestructionHandler(d.data()); + } + d->sourceNode = source; + d->sourceNode->k_ptr->addDestructionHandler(d.data()); + } + return true; + } else { + return false; + } +} + +bool Path::disconnect() +{ + if (!isValid()) { + return false; + } + + QObjectList list; + if (d->sourceNode) + list << d->sourceNode->k_ptr->backendObject(); +#ifndef QT_NO_PHONON_EFFECT + for (int i = 0; i < d->effects.count(); ++i) { + list << d->effects.at(i)->k_ptr->backendObject(); + } +#endif + if (d->sinkNode) { + list << d->sinkNode->k_ptr->backendObject(); + } + + //lets build the disconnection list + QList<QObjectPair> disco; + if (list.count() >=2 ) { + QObjectList::const_iterator it = list.constBegin(); + for(;it+1 != list.constEnd();++it) { + disco << QObjectPair(*it, *(it+1)); + } + } + + if (d->executeTransaction(disco, QList<QObjectPair>())) { + //everything went well, let's remove the reference + //to the paths from the source and sink + if (d->sourceNode) { + d->sourceNode->k_ptr->removeOutputPath(*this); + d->sourceNode->k_ptr->removeDestructionHandler(d.data()); + } + d->sourceNode = 0; + +#ifndef QT_NO_PHONON_EFFECT + for (int i = 0; i < d->effects.count(); ++i) { + d->effects.at(i)->k_ptr->removeDestructionHandler(d.data()); + } + d->effects.clear(); +#endif + + if (d->sinkNode) { + d->sinkNode->k_ptr->removeInputPath(*this); + d->sinkNode->k_ptr->removeDestructionHandler(d.data()); + } + d->sinkNode = 0; + return true; + } else { + return false; + } +} + +MediaNode *Path::source() const +{ + return d->sourceNode; +} + +MediaNode *Path::sink() const +{ + return d->sinkNode; +} + + + +bool PathPrivate::executeTransaction( const QList<QObjectPair> &disconnections, const QList<QObjectPair> &connections) +{ + QSet<QObject*> nodesForTransaction; + for (int i = 0; i < disconnections.count(); ++i) { + const QObjectPair &pair = disconnections.at(i); + nodesForTransaction << pair.first; + nodesForTransaction << pair.second; + } + for (int i = 0; i < connections.count(); ++i) { + const QObjectPair &pair = connections.at(i); + nodesForTransaction << pair.first; + nodesForTransaction << pair.second; + } + BackendInterface *backend = qobject_cast<BackendInterface *>(Factory::backend()); + if (!backend) + return false; + + ConnectionTransaction transaction(backend, nodesForTransaction); + if (!transaction) + return false; + + QList<QObjectPair>::const_iterator it = disconnections.begin(); + for(;it != disconnections.end();++it) { + const QObjectPair &pair = *it; + if (!backend->disconnectNodes(pair.first, pair.second)) { + + //Error: a disconnection failed + QList<QObjectPair>::const_iterator it2 = disconnections.begin(); + for(; it2 != it; ++it2) { + const QObjectPair &pair = *it2; + bool success = backend->connectNodes(pair.first, pair.second); + Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection + Q_UNUSED(success); + } + return false; + } + } + + for(it = connections.begin(); it != connections.end();++it) { + const QObjectPair &pair = *it; + if (!backend->connectNodes(pair.first, pair.second)) { + //Error: a connection failed + QList<QObjectPair>::const_iterator it2 = connections.begin(); + for(; it2 != it; ++it2) { + const QObjectPair &pair = *it2; + bool success = backend->disconnectNodes(pair.first, pair.second); + Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection + Q_UNUSED(success); + } + + //and now let's reconnect the nodes that were disconnected: rollback + for (int i = 0; i < disconnections.count(); ++i) { + const QObjectPair &pair = disconnections.at(i); + bool success = backend->connectNodes(pair.first, pair.second); + Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection + Q_UNUSED(success); + } + + return false; + + } + } + return true; +} + +#ifndef QT_NO_PHONON_EFFECT +bool PathPrivate::removeEffect(Effect *effect) +{ + if (!effects.contains(effect)) + return false; + + QObject *leftNode = 0; + QObject *rightNode = 0; + const int index = effects.indexOf(effect); + if (index == 0) { + leftNode = sourceNode->k_ptr->backendObject(); //append + } else { + leftNode = effects[index - 1]->k_ptr->backendObject(); + } + if (index == effects.size()-1) { + rightNode = sinkNode->k_ptr->backendObject(); //prepend + } else { + rightNode = effects[index + 1]->k_ptr->backendObject(); + } + + QList<QObjectPair> disconnections, connections; + QObject *beffect = effect->k_ptr->backendObject(); + disconnections << QObjectPair(leftNode, beffect) << QObjectPair(beffect, rightNode); + connections << QObjectPair(leftNode, rightNode); + + if (executeTransaction(disconnections, connections)) { + effect->k_ptr->removeDestructionHandler(this); + effects.removeAt(index); + return true; + } + return false; +} +#endif //QT_NO_PHONON_EFFECT + + +void PathPrivate::phononObjectDestroyed(MediaNodePrivate *mediaNodePrivate) +{ + Q_ASSERT(mediaNodePrivate); + if (mediaNodePrivate == sinkNode->k_ptr || mediaNodePrivate == sourceNode->k_ptr) { + //let's first disconnectq the path from its source and sink + QObject *bsink = sinkNode->k_ptr->backendObject(); + QObject *bsource = sourceNode->k_ptr->backendObject(); + QList<QObjectPair> disconnections; +#ifndef QT_NO_PHONON_EFFECT + disconnections << QObjectPair(bsource, effects.isEmpty() ? bsink : effects.first()->k_ptr->backendObject()); + if (!effects.isEmpty()) + disconnections << QObjectPair(effects.last()->k_ptr->backendObject(), bsink); +#else + disconnections << QObjectPair(bsource, bsink); +#endif //QT_NO_PHONON_EFFECT + + executeTransaction(disconnections, QList<QObjectPair>()); + + Path p; //temporary path + p.d = this; + if (mediaNodePrivate == sinkNode->k_ptr) { + sourceNode->k_ptr->removeOutputPath(p); + sourceNode->k_ptr->removeDestructionHandler(this); + } else { + sinkNode->k_ptr->removeInputPath(p); + sinkNode->k_ptr->removeDestructionHandler(this); + } + sourceNode = 0; + sinkNode = 0; + } else { +#ifndef QT_NO_PHONON_EFFECT + for (int i = 0; i < effects.count(); ++i) { + Effect *e = effects.at(i); + if (e->k_ptr == mediaNodePrivate) { + removeEffect(e); + } + } +#endif //QT_NO_PHONON_EFFECT + } +} + +Path createPath(MediaNode *source, MediaNode *sink) +{ + Path p; + if (!p.reconnect(source, sink)) { + const QObject *const src = source ? (source->k_ptr->qObject() +#ifndef QT_NO_DYNAMIC_CAST + ? source->k_ptr->qObject() : dynamic_cast<QObject *>(source) +#endif + ) : 0; + const QObject *const snk = sink ? (sink->k_ptr->qObject() +#ifndef QT_NO_DYNAMIC_CAST + ? sink->k_ptr->qObject() : dynamic_cast<QObject *>(sink) +#endif + ) : 0; + pWarning() << "Phonon::createPath: Cannot connect " + << (src ? src->metaObject()->className() : "") + << '(' << (src ? (src->objectName().isEmpty() ? "no objectName" : qPrintable(src->objectName())) : "null") << ") to " + << (snk ? snk->metaObject()->className() : "") + << '(' << (snk ? (snk->objectName().isEmpty() ? "no objectName" : qPrintable(snk->objectName())) : "null") + << ")."; + } + return p; +} + + +Path & Path::operator=(const Path &other) +{ + d = other.d; + return *this; +} + +bool Path::operator==(const Path &other) const +{ + return d == other.d; +} + +bool Path::operator!=(const Path &other) const +{ + return !operator==(other); +} + +} // namespace Phonon + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/path.h b/src/3rdparty/phonon/phonon/path.h new file mode 100644 index 0000000..6193054 --- /dev/null +++ b/src/3rdparty/phonon/phonon/path.h @@ -0,0 +1,243 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_PATH_H +#define PHONON_PATH_H + +#include "phonon_export.h" +#include "objectdescription.h" + +#include <QtCore/QExplicitlySharedDataPointer> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +template<class T> class QList; + +namespace Phonon +{ + +class PathPrivate; +class Effect; +class MediaNode; + +/** \class Path path.h Phonon/Path + * \short Connection object providing convenient effect insertion + * + * \code +MediaObject *media = new MediaObject; +AudioOutput *output = new AudioOutput(Phonon::MusicCategory); +Path path = Phonon::createPath(media, output); +Q_ASSERT(path.isValid()); // for this simple case the path should always be + //valid - there are unit tests to ensure it +// insert an effect +QList<EffectDescription> effectList = BackendCapabilities::availableAudioEffects(); +if (!effectList.isEmpty()) { + Effect *effect = path.insertEffect(effectList.first()); +} + * \endcode + * \ingroup Playback + * \ingroup Recording + * \author Matthias Kretz <kretz@kde.org> + * \author Thierry Bastian <thierry.bastian@trolltech.com> + */ +class PHONON_EXPORT Path +{ + friend class FactoryPrivate; + public: + /** + * Destroys this reference to the Path. If the path was valid the connection is not broken + * as both the source and the sink MediaNodes still keep a reference to the Path. + * + * \see disconnect + */ + ~Path(); + + /** + * Creates an invalid path. + * + * You can still make it a valid path by calling reconnect. To create a path you should use + * createPath, though. + * + * \see createPath + * \see isValid + */ + Path(); + + /** + * Constructs a copy of the given path. + * + * This constructor is fast thanks to explicit sharing. + */ + Path(const Path &); + + /** + * Returns whether the path object connects two MediaNodes or not. + * + * \return \p true when the path connects two MediaNodes + * \return \p false when the path is disconnected + */ + bool isValid() const; + //MediaStreamTypes mediaStreamTypes() const; + +#ifndef QT_NO_PHONON_EFFECT + /** + * Creates and inserts an effect into the path. + * + * You may insert effects of the same class as often as you like, + * but if you insert the same object, the call will fail. + * + * \param desc The EffectDescription object for the effect to be inserted. + * + * \param insertBefore If you already inserted an effect you can + * tell with this parameter in which order the data gets + * processed. If this is \c 0 the effect is appended at the end of + * the processing list. If the effect has not been inserted before + * the method will do nothing and return \c false. + * + * \return Returns a pointer to the effect object if it could be inserted + * at the specified position. If \c 0 is returned the effect was not + * inserted. + * + * \see removeEffect + * \see effects + */ + Effect *insertEffect(const EffectDescription &desc, Effect *insertBefore = 0); + + /** + * Inserts an effect into the path. + * + * You may insert effects of the same class as often as you like, + * but if you insert the same object, the call will fail. + * + * \param newEffect An Effect object. + * + * \param insertBefore If you already inserted an effect you can + * tell with this parameter in which order the data gets + * processed. If this is \c 0 the effect is appended at the end of + * the processing list. If the effect has not been inserted before + * the method will do nothing and return \c false. + * + * \return Returns whether the effect could be inserted at the + * specified position. If \c false is returned the effect was not + * inserted. + * + * \see removeEffect + * \see effects + */ + bool insertEffect(Effect *newEffect, Effect *insertBefore = 0); + + /** + * Removes an effect from the path. + * + * If the effect gets deleted while it is still connected the effect + * will be removed automatically. + * + * \param effect The effect to be removed. + * + * \return Returns whether the call was successful. If it returns + * \c false the effect could not be found in the path, meaning it + * has not been inserted before. + * + * \see insertEffect + * \see effects + */ + bool removeEffect(Effect *effect); + + /** + * Returns a list of Effect objects that are currently + * used as effects. The order in the list determines the order the + * signal is sent through the effects. + * + * \return A list with all current effects. + * + * \see insertEffect + * \see removeEffect + */ + QList<Effect *> effects() const; +#endif //QT_NO_PHONON_EFFECT + + /** + * Tries to change the MediaNodes the path is connected to. + * + * If reconnect fails the old connection is kept. + */ + bool reconnect(MediaNode *source, MediaNode *sink); + + /** + * Disconnects the path from the MediaNodes it was connected to. This invalidates the path + * (isValid returns \p false then). + */ + bool disconnect(); + + /** + * Assigns \p p to this Path and returns a reference to this Path. + * + * This operation is fast thanks to explicit sharing. + */ + Path &operator=(const Path &p); + + /** + * Returns \p true if this Path is equal to \p p; otherwise returns \p false; + */ + bool operator==(const Path &p) const; + + /** + * Returns \p true if this Path is not equal to \p p; otherwise returns \p false; + */ + bool operator!=(const Path &p) const; + + /** + * Returns the source MediaNode used by the path. + */ + MediaNode *source() const; + + /** + * Returns the sink MediaNode used by the path. + */ + MediaNode *sink() const; + + + protected: + friend class PathPrivate; + QExplicitlySharedDataPointer<PathPrivate> d; +}; + +/** + * \relates Path + * Creates a new Path connecting two MediaNodes. + * + * The implementation will automatically select the right format and media type. E.g. connecting a + * MediaObject and AudioOutput will create a Path object connecting the audio. This might be + * represented as PCM or perhaps even AC3 depending on the AudioOutput object. + * + * \param source The MediaNode to connect an output from + * \param sink The MediaNode to connect to. + */ +PHONON_EXPORT Path createPath(MediaNode *source, MediaNode *sink); + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_PATH_H diff --git a/src/3rdparty/phonon/phonon/path_p.h b/src/3rdparty/phonon/phonon/path_p.h new file mode 100644 index 0000000..51b7e83 --- /dev/null +++ b/src/3rdparty/phonon/phonon/path_p.h @@ -0,0 +1,79 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PATH_P_H +#define PATH_P_H + +#include "path.h" +#include <QtCore/QPair> +#include <QtCore/QList> +#include <QtCore/QSharedData> +#include "effect.h" +#include "medianodedestructionhandler_p.h" + +QT_BEGIN_NAMESPACE + +class QObject; + +namespace Phonon +{ + +class MediaNode; +typedef QPair<QObject*, QObject*> QObjectPair; + + +class PathPrivate : public QSharedData, private MediaNodeDestructionHandler +{ + friend class Path; + public: + PathPrivate() + : sourceNode(0), sinkNode(0) +#ifndef QT_NO_PHONON_EFFECT + , effectsParent(0) +#endif //QT_NO_PHONON_EFFECT + { + } + + ~PathPrivate(); + + MediaNode *sourceNode; + MediaNode *sinkNode; + + protected: + void phononObjectDestroyed(MediaNodePrivate *); + +#ifndef QT_NO_PHONON_EFFECT + QObject *effectsParent; // used as parent for Effects created in insertEffect + QList<Effect *> effects; +#endif + private: + bool executeTransaction( const QList<QObjectPair> &disconnections, const QList<QObjectPair> &connections); +#ifndef QT_NO_PHONON_EFFECT + bool removeEffect(Effect *effect); +#endif +}; + +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // PATH_P_H diff --git a/src/3rdparty/phonon/phonon/phonon_export.h b/src/3rdparty/phonon/phonon/phonon_export.h new file mode 100644 index 0000000..96b5159 --- /dev/null +++ b/src/3rdparty/phonon/phonon/phonon_export.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PHONON_EXPORT_H +#define PHONON_EXPORT_H + +#include <QtCore/QtGlobal> + +#ifndef PHONON_EXPORT +# if defined Q_WS_WIN +# ifdef MAKE_PHONON_LIB /* We are building this library */ +# define PHONON_EXPORT Q_DECL_EXPORT +# else /* We are using this library */ +# define PHONON_EXPORT Q_DECL_IMPORT +# endif +# else /* UNIX */ +# ifdef MAKE_PHONON_LIB /* We are building this library */ +# define PHONON_EXPORT Q_DECL_EXPORT +# else /* We are using this library */ +# define PHONON_EXPORT Q_DECL_IMPORT +# endif +# endif +#endif + +#ifndef PHONON_EXPORT_DEPRECATED +# define PHONON_EXPORT_DEPRECATED Q_DECL_DEPRECATED PHONON_EXPORT +#endif + +// QT_(BEGIN|END)_NAMESPACE appeared in 4.4 +#ifndef QT_BEGIN_NAMESPACE +# define QT_BEGIN_NAMESPACE +#endif +#ifndef QT_END_NAMESPACE +# define QT_END_NAMESPACE +#endif + +// silence syncqt +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/3rdparty/phonon/phonon/phonondefs.h b/src/3rdparty/phonon/phonon/phonondefs.h new file mode 100644 index 0000000..765eb1c --- /dev/null +++ b/src/3rdparty/phonon/phonon/phonondefs.h @@ -0,0 +1,149 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONONDEFS_H +#define PHONONDEFS_H + +#include <QtCore/QtGlobal> +#include "phonon_export.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifdef PHONON_BACKEND_VERSION_4_4 +# ifndef PHONON_BACKEND_VERSION_4_3 +# define PHONON_BACKEND_VERSION_4_3 +# endif +#endif +#ifdef PHONON_BACKEND_VERSION_4_3 +# ifndef PHONON_BACKEND_VERSION_4_2 +# define PHONON_BACKEND_VERSION_4_2 +# endif +#endif + +// the following inlines are correct - exclude per line doesn't work for multiline-macros so exclude +// the whole file for inline checks +//krazy:excludeall=inline +#define K_DECLARE_PRIVATE(Class) \ + inline Class##Private* k_func() { return reinterpret_cast<Class##Private *>(k_ptr); } \ + inline const Class##Private* k_func() const { return reinterpret_cast<const Class##Private *>(k_ptr); } \ + friend class Class##Private; + +/** + * \internal + * Used in class declarations to provide the needed functions. This is used for + * abstract base classes. + * + * \param classname The Name of the class this macro is used for. + * + * Example: + * \code + * class AbstractEffect : public QObject + * { + * Q _OBJECT + * Q_PROPERTY(int propertyA READ propertyA WRITE setPropertyA) + * PHONON_ABSTRACTBASE(AbstractEffect) + * public: + * int propertyA() const; + * void setPropertyA(int); + * }; + * \endcode + * + * \see PHONON_OBJECT + * \see PHONON_HEIR + */ +#define PHONON_ABSTRACTBASE(classname) \ +protected: \ + /** + * \internal + * Constructor that is called from derived classes. + * + * \param parent Standard QObject parent. + */ \ + classname(classname ## Private &dd, QObject *parent); \ +private: + +/** + * \internal + * Used in class declarations to provide the needed functions. This is used for + * classes that inherit QObject directly. + * + * \param classname The Name of the class this macro is used for. + * + * Example: + * \code + * class EffectSettings : public QObject + * { + * Q _OBJECT + * Q_PROPERTY(int propertyA READ propertyA WRITE setPropertyA) + * PHONON_OBJECT(EffectSettings) + * public: + * int propertyA() const; + * void setPropertyA(int); + * }; + * \endcode + * + * \see PHONON_ABSTRACTBASE + * \see PHONON_HEIR + */ +#define PHONON_OBJECT(classname) \ +public: \ + /** + * Constructs an object with the given \p parent. + */ \ + classname(QObject *parent = 0); \ +private: + +/** + * \internal + * Used in class declarations to provide the needed functions. This is used for + * classes that inherit another Phonon object. + * + * \param classname The Name of the class this macro is used for. + * + * Example: + * \code + * class ConcreteEffect : public AbstractEffect + * { + * Q _OBJECT + * Q_PROPERTY(int propertyB READ propertyB WRITE setPropertyB) + * PHONON_HEIR(ConcreteEffect) + * public: + * int propertyB() const; + * void setPropertyB(int); + * }; + * \endcode + * + * \see PHONON_ABSTRACTBASE + * \see PHONON_OBJECT + */ +#define PHONON_HEIR(classname) \ +public: \ + /** + * Constructs an object with the given \p parent. + */ \ + classname(QObject *parent = 0); \ + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONONDEFS_H diff --git a/src/3rdparty/phonon/phonon/phonondefs_p.h b/src/3rdparty/phonon/phonon/phonondefs_p.h new file mode 100644 index 0000000..778d7f6 --- /dev/null +++ b/src/3rdparty/phonon/phonon/phonondefs_p.h @@ -0,0 +1,369 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONONDEFS_P_H +#define PHONONDEFS_P_H + +#include <QtCore/QMetaType> +#include "medianode_p.h" + +#define K_D(Class) Class##Private *const d = k_func() + +#define PHONON_CONCAT_HELPER_INTERNAL(x, y) x ## y +#define PHONON_CONCAT_HELPER(x, y) PHONON_CONCAT_HELPER_INTERNAL(x, y) + +#define PHONON_PRIVATECLASS \ +protected: \ + virtual bool aboutToDeleteBackendObject(); \ + virtual void createBackendObject(); \ + /** + * \internal + * After construction of the Iface object this method is called + * throughout the complete class hierarchy in order to set up the + * properties that were already set on the public interface. + * + * An example implementation could look like this: + * \code + * ParentClassPrivate::setupBackendObject(); + * m_iface->setPropertyA(d->propertyA); + * m_iface->setPropertyB(d->propertyB); + * \endcode + */ \ + void setupBackendObject(); + +#define PHONON_PRIVATEABSTRACTCLASS \ +protected: \ + virtual bool aboutToDeleteBackendObject(); \ + /** + * \internal + * After construction of the Iface object this method is called + * throughout the complete class hierarchy in order to set up the + * properties that were already set on the public interface. + * + * An example implementation could look like this: + * \code + * ParentClassPrivate::setupBackendObject(); + * m_iface->setPropertyA(d->propertyA); + * m_iface->setPropertyB(d->propertyB); + * \endcode + */ \ + void setupBackendObject(); + +#define PHONON_ABSTRACTBASE_IMPL \ +PHONON_CLASSNAME::PHONON_CLASSNAME(PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) &dd, QObject *parent) \ + : QObject(parent), \ + MediaNode(dd) \ +{ \ +} + +#define PHONON_OBJECT_IMPL \ +PHONON_CLASSNAME::PHONON_CLASSNAME(QObject *parent) \ + : QObject(parent), \ + MediaNode(*new PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)()) \ +{ \ +} \ +void PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)::createBackendObject() \ +{ \ + if (m_backendObject) \ + return; \ + Q_Q(PHONON_CLASSNAME); \ + m_backendObject = Factory::PHONON_CONCAT_HELPER(create, PHONON_CLASSNAME)(q); \ + if (m_backendObject) { \ + setupBackendObject(); \ + } \ +} + +#define PHONON_HEIR_IMPL(parentclass) \ +PHONON_CLASSNAME::PHONON_CLASSNAME(QObject *parent) \ + : parentclass(*new PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private), parent) \ +{ \ +} \ +void PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)::createBackendObject() \ +{ \ + if (m_backendObject) \ + return; \ + Q_Q(PHONON_CLASSNAME); \ + m_backendObject = Factory::PHONON_CONCAT_HELPER(create, PHONON_CLASSNAME)(q); \ + if (m_backendObject) { \ + setupBackendObject(); \ + } \ +} + +#define BACKEND_GET(returnType, returnVar, methodName) \ +QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar)) +#define BACKEND_GET1(returnType, returnVar, methodName, varType1, var1) \ +QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1)) +#define BACKEND_GET2(returnType, returnVar, methodName, varType1, var1, varType2, var2) \ +QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1), Q_ARG(varType2, var2)) +#define BACKEND_CALL(methodName) \ +QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection) +#define BACKEND_CALL1(methodName, varType1, var1) \ +QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1)) +#define BACKEND_CALL2(methodName, varType1, var1, varType2, var2) \ +QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1), Q_ARG(varType2, var2)) + +#define pBACKEND_GET(returnType, returnVar, methodName) \ +QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar)) +#define pBACKEND_GET1(returnType, returnVar, methodName, varType1, var1) \ +QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1)) +#define pBACKEND_GET2(returnType, returnVar, methodName, varType1, var1, varType2, var2) \ +QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1), Q_ARG(varType2, var2)) +#define pBACKEND_CALL(methodName) \ +QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection) +#define pBACKEND_CALL1(methodName, varType1, var1) \ +QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1)) +#define pBACKEND_CALL2(methodName, varType1, var1, varType2, var2) \ +QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1), Q_ARG(varType2, var2)) + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + namespace + { + class NoIface; + + /// All template arguments are valid + template<typename T> struct IsValid { enum { Result = true }; }; + /// except NoIface + template<> struct IsValid<NoIface> { enum { Result = false }; }; + + template<class T> inline T my_cast(QObject *o) { return qobject_cast<T>(o); } + template<class T> inline T my_cast(const QObject *o) { return qobject_cast<T>(o); } + + template<> inline NoIface *my_cast<NoIface *>(QObject *) { return 0; } + template<> inline NoIface *my_cast<NoIface *>(const QObject *) { return 0; } + } // anonymous namespace + + /** + * \internal + * + * \brief Helper class to cast the backend object to the correct version of the interface. + * + * Additions to the backend interfaces cannot be done by adding virtual methods as that would + * break the binary interface. So the old class is renamed and a new class with the old name + * inheriting the old class is added, containing all the new virtual methods. + * Example: + * \code + class FooInterface + { + public: + virtual ~FooInterface() {} + virtual oldMethod() = 0; + }; + Q_DECLARE_INTERFACE(FooInterface, "FooInterface0.phonon.kde.org") + * \endcode + * becomes + * \code + class FooInterface0 + { + public: + virtual ~FooInterface0() {} + virtual oldMethod() = 0; + }; + class FooInterface : public FooInterface0 + { + public: + virtual newMethod() = 0; + }; + Q_DECLARE_INTERFACE(FooInterface0, "FooInterface0.phonon.kde.org") + Q_DECLARE_INTERFACE(FooInterface, "FooInterface1.phonon.kde.org") + * \endcode + * + * With this, backends compiled against the old header can be qobject_casted to FooInterface0, + * but not to FooInterface. On the other hand backends compiled against the new header (they first + * need to implement newMethod) can only be qobject_casted to FooInterface but not to + * FooInterface0. (The qobject_cast relies on the string in Q_DECLARE_INTERFACE and not the + * class name which is why it behaves that way.) + * + * Now, in order to call oldMethod, the code needs to try to cast to both FooInterface and + * FooInterface0 (new backends will work with the former, old backends with the latter) and then + * if one of them in non-zero call oldMethod on it. + * + * To call newMethod only a cast to FooInterface needs to be done. + * + * The Iface class does all this for you for up to three (for now) interface revisions. Just + * create an object like this: + * \code + Iface<FooInterface0, FooInterface> iface0(d); + if (iface0) { + iface0->oldMethod(); + } + Iface<FooInterface> iface(d); + if (iface) { + iface->newMethod(); + } + * \endcode + * + * This becomes a bit more convenient if you add macros like this: + * \code + #define IFACES1 FooInterface + #define IFACES0 FooInterface0, IFACES1 + * \endcode + * which you can use like this: + * \code + Iface<IFACES0> iface0(d); + if (iface0) { + iface0->oldMethod(); + } + Iface<IFACES1> iface(d); + if (iface) { + iface->newMethod(); + } + * \endcode + * With the next revision you can then change the macros to + * \code + #define IFACES2 FooInterface + #define IFACES1 FooInterface1, IFACES2 + #define IFACES0 FooInterface0, IFACES1 + * \endcode + * + * \author Matthias Kretz <kretz@kde.org> + */ + template<class T0, class T1 = NoIface, class T2 = NoIface> + class Iface + { + public: + static inline T0 *cast(MediaNodePrivate *const d) + { + if (IsValid<T1>::Result) { + T0 *ret; + if (IsValid<T2>::Result) { + ret = reinterpret_cast<T0 *>(my_cast<T2 *>(d->m_backendObject)); + if (ret) return ret; + } + ret = reinterpret_cast<T0 *>(my_cast<T1 *>(d->m_backendObject)); + if (ret) return ret; + } + return qobject_cast<T0 *>(d->m_backendObject); + } + + static inline const T0 *cast(const MediaNodePrivate *const d) + { + if (IsValid<T1>::Result) { + const T0 *ret; + if (IsValid<T2>::Result) { + ret = reinterpret_cast<const T0 *>(my_cast<T2 *>(d->m_backendObject)); + if (ret) return ret; + } + ret = reinterpret_cast<const T0 *>(my_cast<T1 *>(d->m_backendObject)); + if (ret) return ret; + } + return qobject_cast<T0 *>(d->m_backendObject); + } + + inline Iface(MediaNodePrivate *const d) : iface(cast(d)) {} + inline operator T0 *() { return iface; } + inline operator const T0 *() const { return iface; } + inline T0 *operator->() { Q_ASSERT(iface); return iface; } + inline const T0 *operator->() const { Q_ASSERT(iface); return iface; } + private: + T0 *const iface; + }; + + template<class T0, class T1 = NoIface, class T2 = NoIface> + class ConstIface + { + public: + inline ConstIface(const MediaNodePrivate *const d) : iface(Iface<T0, T1, T2>::cast(d)) {} + inline operator const T0 *() const { return iface; } + inline const T0 *operator->() const { Q_ASSERT(iface); return iface; } + private: + const T0 *const iface; + }; +} // namespace Phonon + +QT_END_NAMESPACE + +#define INTERFACE_CALL(function) \ +Iface<PHONON_INTERFACENAME >::cast(d)->function + +#define pINTERFACE_CALL(function) \ +Iface<PHONON_INTERFACENAME >::cast(this)->function + +#define PHONON_GETTER(rettype, name, retdefault) \ +rettype PHONON_CLASSNAME::name() const \ +{ \ + const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \ + if (!d->m_backendObject) \ + return retdefault; \ + rettype ret; \ + BACKEND_GET(rettype, ret, #name); \ + return ret; \ +} + +#define PHONON_INTERFACE_GETTER(rettype, name, retdefault) \ +rettype PHONON_CLASSNAME::name() const \ +{ \ + const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \ + if (!d->m_backendObject) \ + return retdefault; \ + return Iface<PHONON_INTERFACENAME >::cast(d)->name(); \ +} + +#define PHONON_GETTER1(rettype, name, retdefault, argtype1, argvar1) \ +rettype PHONON_CLASSNAME::name(argtype1 argvar1) const \ +{ \ + const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \ + if (!d->m_backendObject) \ + return retdefault; \ + rettype ret; \ + BACKEND_GET1(rettype, ret, #name, const QObject *, argvar1->k_ptr->backendObject()); \ + return ret; \ +} + +#define PHONON_INTERFACE_GETTER1(rettype, name, retdefault, argtype1, argvar1) \ +rettype PHONON_CLASSNAME::name(argtype1 argvar1) const \ +{ \ + const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \ + if (!d->m_backendObject) \ + return retdefault; \ + return Iface<PHONON_INTERFACENAME >::cast(d)->name(argvar1->k_ptr->backendObject()); \ +} + +#define PHONON_SETTER(functionname, privatevar, argtype1) \ +void PHONON_CLASSNAME::functionname(argtype1 x) \ +{ \ + PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \ + d->privatevar = x; \ + if (k_ptr->backendObject()) { \ + BACKEND_CALL1(#functionname, argtype1, x); \ + } \ +} + +#define PHONON_INTERFACE_SETTER(functionname, privatevar, argtype1) \ +void PHONON_CLASSNAME::functionname(argtype1 x) \ +{ \ + PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \ + d->privatevar = x; \ + if (k_ptr->backendObject()) { \ + Iface<PHONON_INTERFACENAME >::cast(d)->functionname(x); \ + } \ +} + +#ifndef METATYPE_QLIST_INT_DEFINED +#define METATYPE_QLIST_INT_DEFINED +// Want this exactly once, see phonondefs_p.h kcm/outputdevicechoice.cpp +Q_DECLARE_METATYPE(QList<int>) +#endif + +#endif // PHONONDEFS_P_H diff --git a/src/3rdparty/phonon/phonon/phononnamespace.cpp b/src/3rdparty/phonon/phonon/phononnamespace.cpp new file mode 100644 index 0000000..ba20aa5 --- /dev/null +++ b/src/3rdparty/phonon/phonon/phononnamespace.cpp @@ -0,0 +1,92 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "phononnamespace.h" +#include "phononnamespace_p.h" +#include "phonondefs_p.h" + +#include "factory_p.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QList> + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + /*! + Returns the version number of Phonon at run-time as a string (for + example, "4.0.0"). This may be a different version than the + version the application was compiled against. + + \sa PHONON_VERSION_STR + */ + const char *phononVersion() + { + return PHONON_VERSION_STR; + } + + QString categoryToString(Category c) + { + switch(c) + { + case Phonon::NoCategory: + break; + case Phonon::NotificationCategory: + return QCoreApplication::translate("Phonon::", "Notifications"); + case Phonon::MusicCategory: + return QCoreApplication::translate("Phonon::", "Music"); + case Phonon::VideoCategory: + return QCoreApplication::translate("Phonon::", "Video"); + case Phonon::CommunicationCategory: + return QCoreApplication::translate("Phonon::", "Communication"); + case Phonon::GameCategory: + return QCoreApplication::translate("Phonon::", "Games"); + case Phonon::AccessibilityCategory: + return QCoreApplication::translate("Phonon::", "Accessibility"); + } + return QString(); + } +} + +static int registerPhononMetaTypes() +{ + qRegisterMetaType<Phonon::State>(); + qRegisterMetaType<Phonon::ErrorType>(); + qRegisterMetaType<Phonon::Category>(); + + // need those for QSettings + qRegisterMetaType<QList<int> >(); + qRegisterMetaTypeStreamOperators<QList<int> >("QList<int>"); + + return 0; // something +} + +#ifdef Q_CONSTRUCTOR_FUNCTION +Q_CONSTRUCTOR_FUNCTION(registerPhononMetaTypes) +#else +static const int _Phonon_registerMetaTypes = registerPhononMetaTypes(); +#endif + +QT_END_NAMESPACE + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/phononnamespace.h b/src/3rdparty/phonon/phonon/phononnamespace.h new file mode 100644 index 0000000..eb899de --- /dev/null +++ b/src/3rdparty/phonon/phonon/phononnamespace.h @@ -0,0 +1,311 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONONNAMESPACE_H +#define PHONONNAMESPACE_H + +#include "phonon_export.h" + +#ifdef __QT_SYNCQT__ +// Tell syncqt to create a "Global" header here +#pragma qt_class(Phonon::Global) +#endif + +/** + * Helper macro that can be used like + * \code + * #if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 4, 0)) + * \endcode + */ +#define PHONON_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) + +/** + * PHONON_VERSION is (major << 16) + (minor << 8) + patch. + */ +#define PHONON_VERSION PHONON_VERSION_CHECK(4, 4, 0) + +/** + * PHONON_VERSION_STR is "major.minor.patch". E.g. "4.2.1" + */ +#define PHONON_VERSION_STR "4.4.0" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QString; + +/** + * \brief The %KDE Multimedia classes + * + * In this Namespace you find the classes to access Multimedia functions for + * audio and video playback. Those classes are not dependent + * on any specific framework (like they were in pre KDE4 times) but rather use + * exchangeable backends to do the work. + * + * If you want to write a new backend take a look at \ref phonon_backend_development_page. + * + * \author Matthias Kretz <kretz@kde.org> + */ +namespace Phonon +{ + PHONON_EXPORT const char *phononVersion(); + + /** + * Enum to identify the media discs supported by MediaObject. + * + * \see MediaSource(Phonon::DiscType, const QString &deviceName) + */ + enum DiscType { + /** + * No disc was selected. This is only useful as a return value from + * MediaSource::distType(); + */ + NoDisc = -1, + /** + * Identifies Audio CDs. + */ + Cd = 0, + /** + * Identifies DVDs (not arbitrary data DVDs, only movie DVDs). + */ + Dvd = 1, + /** + * Identifies Video CDs. + */ + Vcd = 2 + }; + + /** + * Provided as keys for \ref MediaObject::metaData for convenience, in addition to the strings defined in + * the Ogg Vorbis specification. + */ + enum MetaData { + /** + * The artist generally considered responsible for the work. In popular + * music this is usually the performing band or singer. For classical + * music it would be the composer. For an audio book it would be the + * author of the original text. + */ + ArtistMetaData, + /** + * The collection name to which this track belongs. + */ + AlbumMetaData, + /** + * Track/Work name + */ + TitleMetaData, + /** + * Date the track was recorded + */ + DateMetaData, + /** + * A short text indication of music genre + */ + GenreMetaData, + /** + * The track number of this piece if part of a specific larger + * collection or album + */ + TracknumberMetaData, + /** + * A short text description of the contents + */ + DescriptionMetaData, + MusicBrainzDiscIdMetaData + }; + + /** + * The state the media producing object is in at the moment. + * + * \see MediaObject + */ + enum State + { + /** + * After construction it might take a while before the Player is + * ready to play(). Normally this doesn't happen for local + * files, but can happen for remote files where the asynchronous + * mimetype detection and prebuffering can take a while. + */ + LoadingState, + /** + * The Player has a valid media file loaded and is ready for + * playing. + */ + StoppedState, + /** + * The Player is playing a media file. + */ + PlayingState, + /** + * The Player is waiting for data to be able to continue + * playing. + */ + BufferingState, + /** + * The Player is currently paused. + */ + PausedState, + /** + * An unrecoverable error occurred. The Object is unusable in this state. + */ + ErrorState + }; + + /** + * Set's the category your program should be listed in in the mixer. + * + * A Jukebox will set this to Music, a VoIP program to Communication, a + * DVD player to video, and so on. + * + * \note These categories can also become useful for an application that + * controls the volumes automatically, like turning down the music when a call + * comes in, or turning down the notifications when the media player knows + * it's playing classical music. + * + * \see AudioOutput::setCategory + */ + enum Category + { + /** + * Will make use of the default device. + */ + NoCategory = -1, + /** + * If the sounds produced are notifications (bing, beep and such) you + * should use this category. + */ + NotificationCategory = 0, + /** + * If your application is a music player (like a jukebox or media player + * playing an audio file). + */ + MusicCategory = 1, + /** + * If the sound is the audio channel of a video. + */ + VideoCategory = 2, + /** + * If your applications produces sounds from communication with somebody + * else (VoIP, voice chat). + */ + CommunicationCategory = 3, + /** + * Sound produced by a computer game should go into this category. + */ + GameCategory = 4, + /** + * Sounds produced for accessibility (e.g. Text-To-Speech) + */ + AccessibilityCategory = 5, + /** + * \internal + * Holds the largest value of categories. + */ + LastCategory = AccessibilityCategory + }; + + /** + * Tells your program how to recover from an error. + * + * \see MediaObject::errorType() + */ + enum ErrorType { + /** + * No error. MediaObject::errorType() returns this if + * MediaObject::state() != Phonon::ErrorState. + */ + NoError = 0, + /** + * Playback should work, and trying with another URL should work. + */ + NormalError = 1, + /** + * Something important does not work. Your program cannot continue + * playback or capture or whatever it was trying to do + * without help from the user. + */ + FatalError = 2 + }; + + /** + * Returns a (translated) string to show to the user identifying the given + * Category. + */ + PHONON_EXPORT QString categoryToString(Category c); + + // TODO: naming + /*enum MediaStreamType { + Audio = 1, + Video = 2, + StillImage = 4, + Subtitle = 8, + AllMedia = 0xFFFFFFFF + }; + Q_DECLARE_FLAGS(MediaStreamTypes, MediaStreamType)*/ +} // namespace Phonon +//Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::MediaStreamTypes) + +QT_END_NAMESPACE + +//X class kdbgstream; +//X #include <kdebug.h> +//X /** +//X * Implements needed operator to use Phonon::State with kDebug +//X */ +//X inline PHONON_EXPORT kdbgstream &operator<<(kdbgstream & stream, const Phonon::State state) +//X { +//X switch(state) +//X { +//X case Phonon::ErrorState: +//X stream << "ErrorState"; +//X break; +//X case Phonon::LoadingState: +//X stream << "LoadingState"; +//X break; +//X case Phonon::StoppedState: +//X stream << "StoppedState"; +//X break; +//X case Phonon::PlayingState: +//X stream << "PlayingState"; +//X break; +//X case Phonon::BufferingState: +//X stream << "BufferingState"; +//X break; +//X case Phonon::PausedState: +//X stream << "PausedState"; +//X break; +//X } +//X return stream; +//X } + +#include <QtCore/QMetaType> + +Q_DECLARE_METATYPE(Phonon::State) +Q_DECLARE_METATYPE(Phonon::ErrorType) +Q_DECLARE_METATYPE(Phonon::Category) + +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // PHONONNAMESPACE_H diff --git a/src/3rdparty/phonon/phonon/phononnamespace.h.in b/src/3rdparty/phonon/phonon/phononnamespace.h.in new file mode 100644 index 0000000..c65c121 --- /dev/null +++ b/src/3rdparty/phonon/phonon/phononnamespace.h.in @@ -0,0 +1,306 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONONNAMESPACE_H +#define PHONONNAMESPACE_H + +#include "phonon_export.h" + +/** + * Helper macro that can be used like + * \code + * #if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 4, 0)) + * \endcode + */ +#define PHONON_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) + +/** + * PHONON_VERSION is (major << 16) + (minor << 8) + patch. + */ +#define PHONON_VERSION PHONON_VERSION_CHECK(@PHONON_LIB_MAJOR_VERSION@, @PHONON_LIB_MINOR_VERSION@, @PHONON_LIB_PATCH_VERSION@) + +/** + * PHONON_VERSION_STR is "major.minor.patch". E.g. "4.2.1" + */ +#define PHONON_VERSION_STR "@PHONON_LIB_MAJOR_VERSION@.@PHONON_LIB_MINOR_VERSION@.@PHONON_LIB_PATCH_VERSION@" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QString; + +/** + * \brief The %KDE Multimedia classes + * + * In this Namespace you find the classes to access Multimedia functions for + * audio and video playback. Those classes are not dependent + * on any specific framework (like they were in pre KDE4 times) but rather use + * exchangeable backends to do the work. + * + * If you want to write a new backend take a look at \ref phonon_backend_development_page. + * + * \author Matthias Kretz <kretz@kde.org> + */ +namespace Phonon +{ + PHONON_EXPORT const char *phononVersion(); + + /** + * Enum to identify the media discs supported by MediaObject. + * + * \see MediaSource(Phonon::DiscType, const QString &deviceName) + */ + enum DiscType { + /** + * No disc was selected. This is only useful as a return value from + * MediaSource::distType(); + */ + NoDisc = -1, + /** + * Identifies Audio CDs. + */ + Cd = 0, + /** + * Identifies DVDs (not arbitrary data DVDs, only movie DVDs). + */ + Dvd = 1, + /** + * Identifies Video CDs. + */ + Vcd = 2 + }; + + /** + * Provided as keys for MediaObject::metaData for convenience, in addition to the strings defined in + * the Ogg Vorbis specification. + */ + enum MetaData { + /** + * The artist generally considered responsible for the work. In popular + * music this is usually the performing band or singer. For classical + * music it would be the composer. For an audio book it would be the + * author of the original text. + */ + ArtistMetaData, + /** + * The collection name to which this track belongs. + */ + AlbumMetaData, + /** + * Track/Work name + */ + TitleMetaData, + /** + * Date the track was recorded + */ + DateMetaData, + /** + * A short text indication of music genre + */ + GenreMetaData, + /** + * The track number of this piece if part of a specific larger + * collection or album + */ + TracknumberMetaData, + /** + * A short text description of the contents + */ + DescriptionMetaData, + MusicBrainzDiscIdMetaData + }; + + /** + * The state the media producing object is in at the moment. + * + * \see MediaObject + */ + enum State + { + /** + * After construction it might take a while before the Player is + * ready to play(). Normally this doesn't happen for local + * files, but can happen for remote files where the asynchronous + * mimetype detection and prebuffering can take a while. + */ + LoadingState, + /** + * The Player has a valid media file loaded and is ready for + * playing. + */ + StoppedState, + /** + * The Player is playing a media file. + */ + PlayingState, + /** + * The Player is waiting for data to be able to continue + * playing. + */ + BufferingState, + /** + * The Player is currently paused. + */ + PausedState, + /** + * An unrecoverable error occurred. The Object is unusable in this state. + */ + ErrorState + }; + + /** + * Set's the category your program should be listed in in the mixer. + * + * A Jukebox will set this to Music, a VoIP program to Communication, a + * DVD player to video, and so on. + * + * \note These categories can also become useful for an application that + * controls the volumes automatically, like turning down the music when a call + * comes in, or turning down the notifications when the media player knows + * it's playing classical music. + * + * \see AudioOutput::setCategory + */ + enum Category + { + /** + * Will make use of the default device. + */ + NoCategory = -1, + /** + * If the sounds produced are notifications (bing, beep and such) you + * should use this category. + */ + NotificationCategory = 0, + /** + * If your application is a music player (like a jukebox or media player + * playing an audio file). + */ + MusicCategory = 1, + /** + * If the sound is the audio channel of a video. + */ + VideoCategory = 2, + /** + * If your applications produces sounds from communication with somebody + * else (VoIP, voice chat). + */ + CommunicationCategory = 3, + /** + * Sound produced by a computer game should go into this category. + */ + GameCategory = 4, + /** + * Sounds produced for accessibility (e.g. Text-To-Speech) + */ + AccessibilityCategory = 5, + /** + * \internal + * Holds the largest value of categories. + */ + LastCategory = AccessibilityCategory + }; + + /** + * Tells your program how to recover from an error. + * + * \see MediaObject::errorType() + */ + enum ErrorType { + /** + * No error. MediaObject::errorType() returns this if + * MediaObject::state() != Phonon::ErrorState. + */ + NoError = 0, + /** + * Playback should work, and trying with another URL should work. + */ + NormalError = 1, + /** + * Something important does not work. Your program cannot continue + * playback or capture or whatever it was trying to do + * without help from the user. + */ + FatalError = 2 + }; + + /** + * Returns a (translated) string to show to the user identifying the given + * Category. + */ + PHONON_EXPORT QString categoryToString(Category c); + + // TODO: naming + /*enum MediaStreamType { + Audio = 1, + Video = 2, + StillImage = 4, + Subtitle = 8, + AllMedia = 0xFFFFFFFF + }; + Q_DECLARE_FLAGS(MediaStreamTypes, MediaStreamType)*/ +} // namespace Phonon +//Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::MediaStreamTypes) + +QT_END_NAMESPACE + +//X class kdbgstream; +//X #include <kdebug.h> +//X /** +//X * Implements needed operator to use Phonon::State with kDebug +//X */ +//X inline PHONON_EXPORT kdbgstream &operator<<(kdbgstream & stream, const Phonon::State state) +//X { +//X switch(state) +//X { +//X case Phonon::ErrorState: +//X stream << "ErrorState"; +//X break; +//X case Phonon::LoadingState: +//X stream << "LoadingState"; +//X break; +//X case Phonon::StoppedState: +//X stream << "StoppedState"; +//X break; +//X case Phonon::PlayingState: +//X stream << "PlayingState"; +//X break; +//X case Phonon::BufferingState: +//X stream << "BufferingState"; +//X break; +//X case Phonon::PausedState: +//X stream << "PausedState"; +//X break; +//X } +//X return stream; +//X } + +#include <QtCore/QMetaType> + +Q_DECLARE_METATYPE(Phonon::State) +Q_DECLARE_METATYPE(Phonon::ErrorType) +Q_DECLARE_METATYPE(Phonon::Category) + +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // PHONONNAMESPACE_H diff --git a/src/3rdparty/phonon/phonon/phononnamespace_p.h b/src/3rdparty/phonon/phonon/phononnamespace_p.h new file mode 100644 index 0000000..2fa520a --- /dev/null +++ b/src/3rdparty/phonon/phonon/phononnamespace_p.h @@ -0,0 +1,38 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONONNAMESPACE_P_H +#define PHONONNAMESPACE_P_H + +#include <QtCore/QDebug> + +#if defined(QT_NO_DEBUG) +#define pDebug if (true) {} else qDebug +#else +#define pDebug if (qgetenv("PHONON_DEBUG").isEmpty()) {} else qDebug +#endif +#define pWarning() qDebug() << "WARNING:" +#define pError() qDebug() << "ERROR:" +#define pFatal(message) qDebug() << "FATAL ERROR:" << message; ::abort() + +// vim: sw=4 ts=4 tw=80 +#endif // PHONONNAMESPACE_P_H diff --git a/src/3rdparty/phonon/phonon/platform.cpp b/src/3rdparty/phonon/phonon/platform.cpp new file mode 100644 index 0000000..49c4561 --- /dev/null +++ b/src/3rdparty/phonon/phonon/platform.cpp @@ -0,0 +1,144 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "platform_p.h" +#include "platformplugin.h" +#include "factory_p.h" +#include <QtCore/QCoreApplication> +#include <QtCore/QUrl> +#include <QtGui/QIcon> +#include <QtGui/QStyle> +#include <QtGui/QApplication> + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +void Platform::saveVolume(const QString &outputName, qreal volume) +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + PlatformPlugin *f = Factory::platformPlugin(); + if (f) { + f->saveVolume(outputName, volume); + } +#else + Q_UNUSED(outputName); + Q_UNUSED(volume); +#endif //QT_NO_PHONON_PLATFORMPLUGIN +} + +qreal Platform::loadVolume(const QString &outputName) +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + const PlatformPlugin *f = Factory::platformPlugin(); + if (f) { + return f->loadVolume(outputName); + } +#else + Q_UNUSED(outputName); +#endif //QT_NO_PHONON_PLATFORMPLUGIN + return 1.0; +} + +AbstractMediaStream *Platform::createMediaStream(const QUrl &url, QObject *parent) +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + PlatformPlugin *f = Factory::platformPlugin(); + if (f) { + return f->createMediaStream(url, parent); + } +#else + Q_UNUSED(url); + Q_UNUSED(parent); +#endif //QT_NO_PHONON_PLATFORMPLUGIN + return 0; +} + +QIcon Platform::icon(const QString &name, QStyle *style) +{ + QIcon ret; +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + if (const PlatformPlugin *f = Factory::platformPlugin()) { + ret = f->icon(name); + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + if (ret.isNull()) { + if (!style) { + style = QApplication::style(); + } + if (name == QLatin1String("player-volume")) { + ret = style->standardPixmap(QStyle::SP_MediaVolume); + } else if (name == QLatin1String("player-volume-muted")) { + ret = style->standardPixmap(QStyle::SP_MediaVolumeMuted); + } + } + + return ret; +} + +void Platform::notification(const char *notificationName, const QString &text, + const QStringList &actions, QObject *receiver, + const char *actionSlot) +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + const PlatformPlugin *f = Factory::platformPlugin(); + if (f) { + f->notification(notificationName, text, actions, receiver, actionSlot); + } +#else + Q_UNUSED(notificationName); + Q_UNUSED(text); + Q_UNUSED(actions); + Q_UNUSED(receiver); + Q_UNUSED(actionSlot); +#endif //QT_NO_PHONON_PLATFORMPLUGIN +} + +QString Platform::applicationName() +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + const PlatformPlugin *f = Factory::platformPlugin(); + if (f) { + return f->applicationName(); + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + QString ret = QCoreApplication::applicationName(); + if (ret.isEmpty()) + ret = QCoreApplication::applicationFilePath(); + return ret; +} + +QList<QPair<QByteArray, QString> > Platform::deviceAccessListFor(const Phonon::AudioOutputDevice &deviceDesc) +{ +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + const PlatformPlugin *f = Factory::platformPlugin(); + if (f) { + return f->deviceAccessListFor(deviceDesc); + } +#endif //QT_NO_PHONON_PLATFORMPLUGIN + return QList<QPair<QByteArray, QString> >(); +} + +} // namespace Phonon + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/phonon/platform_p.h b/src/3rdparty/phonon/phonon/platform_p.h new file mode 100644 index 0000000..c4edb2f --- /dev/null +++ b/src/3rdparty/phonon/phonon/platform_p.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_PLATFORM_P_H +#define PHONON_PLATFORM_P_H + + +#include <QtCore/QStringList> +#include <QtCore/QtGlobal> +#include <QtCore/QPair> +#include "phonon_export.h" +#include "objectdescription.h" + +QT_BEGIN_NAMESPACE + +class QIcon; +class QObject; +class QUrl; +class QStyle; + +namespace Phonon +{ +class AbstractMediaStream; + +namespace Platform +{ + +void saveVolume(const QString &outputName, qreal volume); +qreal loadVolume(const QString &outputName); +AbstractMediaStream *createMediaStream(const QUrl &url, QObject *parent); +QIcon icon(const QString &name, QStyle *style = 0); +void notification(const char *notificationName, const QString &text, + const QStringList &actions = QStringList(), QObject *receiver = 0, + const char *actionSlot = 0); +QString applicationName(); +QList<QPair<QByteArray, QString> > deviceAccessListFor(const Phonon::AudioOutputDevice &deviceDesc); + +} // namespace Platform +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // PHONON_PLATFORM_P_H diff --git a/src/3rdparty/phonon/phonon/platformplugin.h b/src/3rdparty/phonon/phonon/platformplugin.h new file mode 100644 index 0000000..c75bc96 --- /dev/null +++ b/src/3rdparty/phonon/phonon/platformplugin.h @@ -0,0 +1,118 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_PLATFORMPLUGIN_H +#define PHONON_PLATFORMPLUGIN_H + +#include <QtCore/QObject> +#include <QtCore/QStringList> +#include <QtCore/QPair> +#include "phonon_export.h" +#include "objectdescription.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + +class QUrl; +class QObject; +class QIcon; + +namespace Phonon +{ +class AbstractMediaStream; + +class PlatformPlugin +{ + public: + virtual ~PlatformPlugin() {} + + /** + * Creates a AbstractMediaStream object that provides the data for the given \p url. On KDE + * this uses KIO. + */ + virtual AbstractMediaStream *createMediaStream(const QUrl &url, QObject *parent) = 0; + + /** + * Returns the icon for the given icon name. + */ + virtual QIcon icon(const QString &name) const = 0; + + /** + * Shows a notification popup + */ + virtual void notification(const char *notificationName, const QString &text, + const QStringList &actions = QStringList(), QObject *receiver = 0, + const char *actionSlot = 0) const = 0; + + /** + * Returns the name of the application. For most Qt application this is + * QCoreApplication::applicationName(), but for KDE this is overridden by KAboutData. + */ + virtual QString applicationName() const = 0; + + /** + * Creates a backend object. This way the platform can decide the backend preference. + */ + virtual QObject *createBackend() = 0; + + /** + * Using the library loader of the platform, loads a given backend. + */ + virtual QObject *createBackend(const QString &library, const QString &version) = 0; + + /** + * Tries to check whether the default backend supports a given MIME type without loading the + * actual backend library. On KDE this reads the MIME type list from the .desktop file of + * the backend. + */ + virtual bool isMimeTypeAvailable(const QString &mimeType) const = 0; + + /** + * Saves the volume for the given output. + */ + virtual void saveVolume(const QString &outputName, qreal volume) = 0; + + /** + * Loads the volume for the given output. + */ + virtual qreal loadVolume(const QString &outputName) const = 0; + + virtual QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const = 0; + virtual QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const = 0; + + /** + * Returns a list of (driver, handle) pairs for the given AudioOutputDevice description. + */ + virtual QList<QPair<QByteArray, QString> > deviceAccessListFor(const Phonon::AudioOutputDevice &) const { return QList<QPair<QByteArray, QString> >(); } +}; +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::PlatformPlugin, "3PlatformPlugin.phonon.kde.org") + +#endif //QT_NO_PHONON_PLATFORMPLUGIN + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_PLATFORMPLUGIN_H diff --git a/src/3rdparty/phonon/phonon/preprocessandextract.sh b/src/3rdparty/phonon/phonon/preprocessandextract.sh new file mode 100755 index 0000000..13b1704 --- /dev/null +++ b/src/3rdparty/phonon/phonon/preprocessandextract.sh @@ -0,0 +1,39 @@ +#!/bin/sh +EXTRACT="`dirname $0`/extractmethodcalls.rb" +IGNORE="^\(streameventqueue\|abstractmediastream2\|lockfreequeue\|path\|platform\|iodevicestream\|medianode\|streaminterface\|mediasource\|abstractmediastream\|audioplayer\|globalconfig\|objectdescriptionmodel\|audiooutputadaptor\|effectwidget\|videoplayer\|seekslider\|volumeslider\).cpp$" + +if test -n "$1" -a -f "$1"; then + echo "preprocessing $1" + cpp $1 2>/dev/null > tmp + echo "extracting backend calls from $1" + $EXTRACT tmp > tests/methods/$1 + rm tmp +else + for i in *.cpp; do + if echo $i | grep -q "$IGNORE"; then + printf "%-30s ignored.\n" "$i:" + elif echo $i | grep -q '_p\.cpp$'; then + printf "%-30s postponed.\n" "$i:" + else + printf "%-30s preprocessing" "$i:" + cpp $i 2>/dev/null > tmp + echo -n ", extracting backend calls" + $EXTRACT tmp > tests/methods/$i + rm tmp + echo "." + fi + done + for i in *_p.cpp; do + cpp=`echo $i | sed 's,_p\.cpp$,\.cpp,'` + if echo $cpp | grep -q "$IGNORE"; then + printf "%-30s ignored.\n" "$i:" + elif test "$i" != "*_p.cpp"; then + printf "%-30s preprocessing" "$i:" + cpp $i 2>/dev/null > tmp + echo -n ", extracting backend calls" + $EXTRACT tmp >> tests/methods/$cpp + rm tmp + echo "." + fi + done +fi diff --git a/src/3rdparty/phonon/phonon/pulsesupport.cpp b/src/3rdparty/phonon/phonon/pulsesupport.cpp new file mode 100644 index 0000000..b1ba196 --- /dev/null +++ b/src/3rdparty/phonon/phonon/pulsesupport.cpp @@ -0,0 +1,1038 @@ +/* This file is part of the KDE project + Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <QtCore/QAbstractEventDispatcher> +#include <QtCore/QEventLoop> +#include <QtCore/QDebug> +#include <QtCore/QStringList> + +#ifdef HAVE_PULSEAUDIO +#include <glib.h> +#include <pulse/pulseaudio.h> +#include <pulse/xmalloc.h> +#include <pulse/glib-mainloop.h> +#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER +# include <pulse/ext-device-manager.h> +#endif +#endif // HAVE_PULSEAUDIO + +#include "pulsesupport.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +static PulseSupport* s_instance = NULL; + +#ifdef HAVE_PULSEAUDIO +/*** +* Prints a conditional debug message based on the current debug level +* If obj is provided, classname and objectname will be printed as well +* +* see debugLevel() +*/ + +static int debugLevel() { + static int level = -1; + if (level < 1) { + level = 0; + QByteArray pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG"); + int l = pulseenv.toInt(); + if (l > 0) + level = (l > 2 ? 2 : l); + } + return level; +} + +static void logMessage(const QString &message, int priority = 2, QObject *obj=0); +static void logMessage(const QString &message, int priority, QObject *obj) +{ + if (debugLevel() > 0) { + QString output; + if (obj) { + // Strip away namespace from className + QByteArray className(obj->metaObject()->className()); + int nameLength = className.length() - className.lastIndexOf(':') - 1; + className = className.right(nameLength); + output.sprintf("%s %s (%s %p)", message.toLatin1().constData(), + obj->objectName().toLatin1().constData(), + className.constData(), obj); + } + else { + output = message; + } + if (priority <= debugLevel()) { + qDebug() << QString::fromLatin1("PulseSupport(%1): %2").arg(priority).arg(output); + } + } +} + + +class AudioDevice +{ + public: + inline + AudioDevice(QString name, QString desc, QString icon, uint32_t index) + : pulseName(name), pulseIndex(index) + { + properties["name"] = desc; + properties["description"] = QLatin1String(""); // We don't have descriptions (well we do, but we use them as the name!) + properties["icon"] = icon; + properties["available"] = (index != PA_INVALID_INDEX); + properties["isAdvanced"] = false; // Nothing is advanced! + } + + // Needed for QMap + inline AudioDevice() {} + + QString pulseName; + uint32_t pulseIndex; + QHash<QByteArray, QVariant> properties; +}; +bool operator!=(const AudioDevice &a, const AudioDevice &b) +{ + return !(a.pulseName == b.pulseName && a.properties == b.properties); +} + +class PulseUserData +{ + public: + inline + PulseUserData() + { + } + + QMap<QString, AudioDevice> newOutputDevices; + QMap<Phonon::Category, QMap<int, int> > newOutputDevicePriorities; // prio, device + + QMap<QString, AudioDevice> newCaptureDevices; + QMap<Phonon::Category, QMap<int, int> > newCaptureDevicePriorities; // prio, device +}; + +static QMap<QString, Phonon::Category> s_roleCategoryMap; + +static bool s_pulseActive = false; + +static pa_glib_mainloop *s_mainloop = NULL; +static pa_context *s_context = NULL; + + + +static int s_deviceIndexCounter = 0; + +static QMap<QString, int> s_outputDeviceIndexes; +static QMap<int, AudioDevice> s_outputDevices; +static QMap<Phonon::Category, QMap<int, int> > s_outputDevicePriorities; // prio, device +static QMap<QString, uint32_t> s_outputStreamIndexMap; + +static QMap<QString, int> s_captureDeviceIndexes; +static QMap<int, AudioDevice> s_captureDevices; +static QMap<Phonon::Category, QMap<int, int> > s_captureDevicePriorities; // prio, device +static QMap<QString, uint32_t> s_captureStreamIndexMap; + +static void createGenericDevices() +{ + // OK so we don't have the device manager extension, but we can show a single device and fake it. + int index; + s_outputDeviceIndexes.clear(); + s_outputDevices.clear(); + s_outputDevicePriorities.clear(); + index = s_deviceIndexCounter++; + s_outputDeviceIndexes.insert(QLatin1String("sink:default"), index); + s_outputDevices.insert(index, AudioDevice(QLatin1String("sink:default"), QObject::tr("PulseAudio Sound Server"), QLatin1String("audio-backend-pulseaudio"), 0)); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast<Phonon::Category>(i); + s_outputDevicePriorities[cat].insert(0, index); + } + + s_captureDeviceIndexes.clear(); + s_captureDevices.clear(); + s_captureDevicePriorities.clear(); + index = s_deviceIndexCounter++; + s_captureDeviceIndexes.insert(QLatin1String("source:default"), index); + s_captureDevices.insert(index, AudioDevice(QLatin1String("source:default"), QObject::tr("PulseAudio Sound Server"), QLatin1String("audio-backend-pulseaudio"), 0)); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast<Phonon::Category>(i); + s_captureDevicePriorities[cat].insert(0, index); + } +} + +#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER +static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manager_info *info, int eol, void *userdata) { + Q_ASSERT(c); + Q_ASSERT(userdata); + + PulseUserData *u = reinterpret_cast<PulseUserData*>(userdata); + + if (eol < 0) { + logMessage(QString("Failed to initialize device manager extension: %1").arg(pa_strerror(pa_context_errno(c)))); + logMessage("Falling back to single device mode"); + createGenericDevices(); + delete u; + + // If this is our probe phase, exit now + if (s_context != c) + pa_context_disconnect(c); + + return; + } + + if (eol) { + // We're done reading the data, so order it by priority and copy it into the + // static variables where it can then be accessed by those classes that need it. + + QMap<QString, AudioDevice>::iterator newdev_it; + + // Check for new output devices or things changing about known output devices. + bool output_changed = false; + for (newdev_it = u->newOutputDevices.begin(); newdev_it != u->newOutputDevices.end(); ++newdev_it) { + QString name = newdev_it.key(); + + // The name + index map is always written when a new device is added. + Q_ASSERT(s_outputDeviceIndexes.contains(name)); + + int index = s_outputDeviceIndexes[name]; + if (!s_outputDevices.contains(index)) { + // This is a totally new device + output_changed = true; + logMessage(QString("Brand New Output Device Found.")); + s_outputDevices.insert(index, *newdev_it); + } else if (s_outputDevices[index] != *newdev_it) { + // We have this device already, but is it different? + output_changed = true; + logMessage(QString("Change to Existing Output Device (may be Added/Removed or something else)")); + s_outputDevices.remove(index); + s_outputDevices.insert(index, *newdev_it); + } + } + // Go through the output devices we know about and see if any are no longer mentioned in the list. + QMutableMapIterator<QString, int> output_existing_it(s_outputDeviceIndexes); + while (output_existing_it.hasNext()) { + output_existing_it.next(); + if (!u->newOutputDevices.contains(output_existing_it.key())) { + output_changed = true; + logMessage(QString("Output Device Completely Removed")); + s_outputDevices.remove(output_existing_it.value()); + output_existing_it.remove(); + } + } + + // Check for new capture devices or things changing about known capture devices. + bool capture_changed = false; + for (newdev_it = u->newCaptureDevices.begin(); newdev_it != u->newCaptureDevices.end(); ++newdev_it) { + QString name = newdev_it.key(); + + // The name + index map is always written when a new device is added. + Q_ASSERT(s_captureDeviceIndexes.contains(name)); + + int index = s_captureDeviceIndexes[name]; + if (!s_captureDevices.contains(index)) { + // This is a totally new device + capture_changed = true; + logMessage(QString("Brand New Capture Device Found.")); + s_captureDevices.insert(index, *newdev_it); + } else if (s_captureDevices[index] != *newdev_it) { + // We have this device already, but is it different? + capture_changed = true; + logMessage(QString("Change to Existing Capture Device (may be Added/Removed or something else)")); + s_captureDevices.remove(index); + s_captureDevices.insert(index, *newdev_it); + } + } + // Go through the capture devices we know about and see if any are no longer mentioned in the list. + QMutableMapIterator<QString, int> capture_existing_it(s_captureDeviceIndexes); + while (capture_existing_it.hasNext()) { + capture_existing_it.next(); + if (!u->newCaptureDevices.contains(capture_existing_it.key())) { + capture_changed = true; + logMessage(QString("Capture Device Completely Removed")); + s_captureDevices.remove(capture_existing_it.value()); + capture_existing_it.remove(); + } + } + + // Just copy accross the new priority lists as we know they are valid + if (s_outputDevicePriorities != u->newOutputDevicePriorities) { + output_changed = true; + s_outputDevicePriorities = u->newOutputDevicePriorities; + } + if (s_captureDevicePriorities != u->newCaptureDevicePriorities) { + capture_changed = true; + s_captureDevicePriorities = u->newCaptureDevicePriorities; + } + + if (s_instance) { + // This wont be emitted durring the connection probe phase + // which is intensional + if (output_changed) + s_instance->emitObjectDescriptionChanged(AudioOutputDeviceType); + if (capture_changed) + s_instance->emitObjectDescriptionChanged(AudioCaptureDeviceType); + } + + // We can free the user data as we will not be called again. + delete u; + + // Some debug + logMessage(QString("Output Device Priority List:")); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast<Phonon::Category>(i); + if (s_outputDevicePriorities.contains(cat)) { + logMessage(QString(" Phonon Category %1").arg(cat)); + int count = 0; + foreach (int j, s_outputDevicePriorities[cat]) { + QHash<QByteArray, QVariant> &props = s_outputDevices[j].properties; + logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool())); + } + } + } + logMessage(QString("Capture Device Priority List:")); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast<Phonon::Category>(i); + if (s_captureDevicePriorities.contains(cat)) { + logMessage(QString(" Phonon Category %1").arg(cat)); + int count = 0; + foreach (int j, s_captureDevicePriorities[cat]) { + QHash<QByteArray, QVariant> &props = s_captureDevices[j].properties; + logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool())); + } + } + } + + // If this is our probe phase, exit now as we're finished reading + // our device info and can exit and reconnect + if (s_context != c) + pa_context_disconnect(c); + } + + if (!info) + return; + + Q_ASSERT(info->name); + Q_ASSERT(info->description); + Q_ASSERT(info->icon); + + // QString wrapper + QString name(info->name); + int index; + QMap<Phonon::Category, QMap<int, int> > *new_prio_map_cats; // prio, device + QMap<QString, AudioDevice> *new_devices; + + if (name.startsWith("sink:")) { + new_devices = &u->newOutputDevices; + new_prio_map_cats = &u->newOutputDevicePriorities; + + if (s_outputDeviceIndexes.contains(name)) + index = s_outputDeviceIndexes[name]; + else + index = s_outputDeviceIndexes[name] = s_deviceIndexCounter++; + } else if (name.startsWith("source:")) { + new_devices = &u->newCaptureDevices; + new_prio_map_cats = &u->newCaptureDevicePriorities; + + if (s_captureDeviceIndexes.contains(name)) + index = s_captureDeviceIndexes[name]; + else + index = s_captureDeviceIndexes[name] = s_deviceIndexCounter++; + } else { + // This indicates a bug in pulseaudio. + return; + } + + // Add the new device itself. + new_devices->insert(name, AudioDevice(name, info->description, info->icon, info->index)); + + // For each role in the priority, map it to a phonon category and store the order. + for (uint32_t i = 0; i < info->n_role_priorities; ++i) { + pa_ext_device_manager_role_priority_info* role_prio = &info->role_priorities[i]; + Q_ASSERT(role_prio->role); + + if (s_roleCategoryMap.contains(role_prio->role)) { + Phonon::Category cat = s_roleCategoryMap[role_prio->role]; + + (*new_prio_map_cats)[cat].insert(role_prio->priority, index); + } + } +} + +static void ext_device_manager_subscribe_cb(pa_context *c, void *) { + Q_ASSERT(c); + + pa_operation *o; + PulseUserData *u = new PulseUserData; + if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) { + logMessage(QString("pa_ext_device_manager_read() failed.")); + delete u; + return; + } + pa_operation_unref(o); +} +#endif + +void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) { + Q_UNUSED(userdata); + Q_ASSERT(c); + + if (eol < 0) { + if (pa_context_errno(c) == PA_ERR_NOENTITY) + return; + + logMessage(QLatin1String("Sink input callback failure")); + return; + } + + if (eol > 0) + return; + + Q_ASSERT(i); + + // loop through (*i) and extract phonon->streamindex... + const char *t; + if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { + logMessage(QString::fromLatin1("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(QLatin1String(t))); + s_outputStreamIndexMap[QLatin1String(t)] = i->index; + + // Find the sink's phonon index and notify whoever cares... + if (PA_INVALID_INDEX != i->sink) { + bool found = false; + int device; + QMap<int, AudioDevice>::iterator it; + for (it = s_outputDevices.begin(); it != s_outputDevices.end(); ++it) { + if ((*it).pulseIndex == i->sink) { + found = true; + device = it.key(); + break; + } + } + if (found) { + // OK so we just emit our signal + logMessage(QLatin1String("Letting the rest of phonon know about this")); + s_instance->emitUsingDevice(QLatin1String(t), device); + } + } + } +} + +void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, void *userdata) { + Q_UNUSED(userdata); + Q_ASSERT(c); + + if (eol < 0) { + if (pa_context_errno(c) == PA_ERR_NOENTITY) + return; + + logMessage(QLatin1String("Source output callback failure")); + return; + } + + if (eol > 0) + return; + + Q_ASSERT(i); + + // loop through (*i) and extract phonon->streamindex... + const char *t; + if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { + logMessage(QString::fromLatin1("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(QLatin1String(t))); + s_captureStreamIndexMap[QLatin1String(t)] = i->index; + + // Find the source's phonon index and notify whoever cares... + if (PA_INVALID_INDEX != i->source) { + bool found = false; + int device; + QMap<int, AudioDevice>::iterator it; + for (it = s_captureDevices.begin(); it != s_captureDevices.end(); ++it) { + if ((*it).pulseIndex == i->source) { + found = true; + device = it.key(); + break; + } + } + if (found) { + // OK so we just emit our signal + logMessage(QLatin1String("Letting the rest of phonon know about this")); + s_instance->emitUsingDevice(QLatin1String(t), device); + } + } + } +} + +static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) { + Q_UNUSED(userdata); + + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + QString phononid = s_outputStreamIndexMap.key(index); + if (!phononid.isEmpty()) { + if (s_outputStreamIndexMap.contains(phononid)) { + logMessage(QString::fromLatin1("Phonon Output Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); + s_outputStreamIndexMap[phononid] = PA_INVALID_INDEX; + } else { + logMessage(QString::fromLatin1("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid)); + s_outputStreamIndexMap.remove(phononid); + } + } + } else { + pa_operation *o; + if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, NULL))) { + logMessage(QLatin1String("pa_context_get_sink_input_info() failed")); + return; + } + pa_operation_unref(o); + } + break; + + case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + QString phononid = s_captureStreamIndexMap.key(index); + if (!phononid.isEmpty()) { + if (s_captureStreamIndexMap.contains(phononid)) { + logMessage(QString::fromLatin1("Phonon Capture Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); + s_captureStreamIndexMap[phononid] = PA_INVALID_INDEX; + } else { + logMessage(QString::fromLatin1("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid)); + s_captureStreamIndexMap.remove(phononid); + } + } + } else { + pa_operation *o; + if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, NULL))) { + logMessage(QLatin1String("pa_context_get_sink_input_info() failed")); + return; + } + pa_operation_unref(o); + } + break; + } +} + + +static QString statename(pa_context_state_t state) +{ + switch (state) + { + case PA_CONTEXT_UNCONNECTED: return QLatin1String("Unconnected"); + case PA_CONTEXT_CONNECTING: return QLatin1String("Connecting"); + case PA_CONTEXT_AUTHORIZING: return QLatin1String("Authorizing"); + case PA_CONTEXT_SETTING_NAME: return QLatin1String("Setting Name"); + case PA_CONTEXT_READY: return QLatin1String("Ready"); + case PA_CONTEXT_FAILED: return QLatin1String("Failed"); + case PA_CONTEXT_TERMINATED: return QLatin1String("Terminated"); + } + + return QString::fromLatin1("Unknown state: %0").arg(state); +} + +static void context_state_callback(pa_context *c, void *) +{ + Q_ASSERT(c); + + logMessage(QString::fromLatin1("context_state_callback %1").arg(statename(pa_context_get_state(c)))); + pa_context_state_t state = pa_context_get_state(c); + if (state == PA_CONTEXT_READY) { + // We've connected to PA, so it is active + s_pulseActive = true; + + // Attempt to load things up + pa_operation *o; + + // 1. Register for the stream changes (except during probe) + if (s_context == c) { + pa_context_set_subscribe_callback(c, subscribe_cb, NULL); + + if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK_INPUT| + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) { + logMessage(QLatin1String("pa_context_subscribe() failed")); + return; + } + pa_operation_unref(o); + } + +#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER + // 2a. Attempt to initialise Device Manager info (except during probe) + if (s_context == c) { + pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, NULL); + if (!(o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL))) { + logMessage(QString("pa_ext_device_manager_subscribe() failed")); + return; + } + pa_operation_unref(o); + } + + // 3. Attempt to read info from Device Manager + PulseUserData *u = new PulseUserData; + if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) { + logMessage(QString("pa_ext_device_manager_read() failed. Attempting to continue without device manager support")); + createGenericDevices(); + delete u; + + // If this is our probe phase, exit immediately + if (s_context != c) + pa_context_disconnect(c); + + return; + } + pa_operation_unref(o); + +#else + // If we know do not have Device Manager support, we just create our dummy devices now + createGenericDevices(); + + // If this is our probe phase, exit immediately + if (s_context != c) + pa_context_disconnect(c); +#endif + } else if (!PA_CONTEXT_IS_GOOD(state)) { + /// @todo Deal with reconnection... + //logMessage("Connection to PulseAudio lost"); + + // If this is our probe phase, exit our context immediately + if (s_context != c) + pa_context_disconnect(c); + } +} +#endif // HAVE_PULSEAUDIO + + +PulseSupport* PulseSupport::getInstance() +{ + if (NULL == s_instance) { + s_instance = new PulseSupport(); + } + return s_instance; +} + +void PulseSupport::shutdown() +{ + if (NULL != s_instance) { + delete s_instance; + s_instance = NULL; + } +} + +PulseSupport::PulseSupport() + : QObject(), mEnabled(false) +{ +#ifdef HAVE_PULSEAUDIO + // Initialise our map (is there a better way to do this?) + s_roleCategoryMap[QLatin1String("none")] = Phonon::NoCategory; + s_roleCategoryMap[QLatin1String("video")] = Phonon::VideoCategory; + s_roleCategoryMap[QLatin1String("music")] = Phonon::MusicCategory; + s_roleCategoryMap[QLatin1String("game")] = Phonon::GameCategory; + s_roleCategoryMap[QLatin1String("event")] = Phonon::NotificationCategory; + s_roleCategoryMap[QLatin1String("phone")] = Phonon::CommunicationCategory; + //s_roleCategoryMap[QLatin1String("animation")]; // No Mapping + //s_roleCategoryMap[QLatin1String("production")]; // No Mapping + s_roleCategoryMap[QLatin1String("a11y")] = Phonon::AccessibilityCategory; + + // To allow for easy debugging, give an easy way to disable this pulseaudio check + QByteArray pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE"); + if (pulseenv.toInt()) { + logMessage(QLatin1String("PulseAudio support disabled: PHONON_PULSEAUDIO_DISABLE is set")); + return; + } + + // We require a glib event loop + if (strcmp(QAbstractEventDispatcher::instance()->metaObject()->className(), + "QGuiEventDispatcherGlib") != 0) { + logMessage(QLatin1String("Disabling PulseAudio integration for lack of GLib event loop.")); + return; + } + + // First of all conenct to PA via simple/blocking means and if that succeeds, + // use a fully async integrated mainloop method to connect and get proper support. + pa_mainloop *p_test_mainloop; + if (!(p_test_mainloop = pa_mainloop_new())) { + logMessage(QLatin1String("PulseAudio support disabled: Unable to create mainloop")); + return; + } + + pa_context *p_test_context; + if (!(p_test_context = pa_context_new(pa_mainloop_get_api(p_test_mainloop), "libphonon-probe"))) { + logMessage(QLatin1String("PulseAudio support disabled: Unable to create context")); + pa_mainloop_free(p_test_mainloop); + return; + } + + logMessage(QLatin1String("Probing for PulseAudio...")); + // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required + if (pa_context_connect(p_test_context, NULL, static_cast<pa_context_flags_t>(0), NULL) < 0) { + logMessage(QString::fromLatin1("PulseAudio support disabled: %1").arg(QString::fromLocal8Bit(pa_strerror(pa_context_errno(p_test_context))))); + pa_context_disconnect(p_test_context); + pa_context_unref(p_test_context); + pa_mainloop_free(p_test_mainloop); + return; + } + + pa_context_set_state_callback(p_test_context, &context_state_callback, NULL); + for (;;) { + pa_mainloop_iterate(p_test_mainloop, 1, NULL); + + if (!PA_CONTEXT_IS_GOOD(pa_context_get_state(p_test_context))) { + logMessage(QLatin1String("PulseAudio probe complete.")); + break; + } + } + pa_context_disconnect(p_test_context); + pa_context_unref(p_test_context); + pa_mainloop_free(p_test_mainloop); + + if (!s_pulseActive) { + logMessage(QLatin1String("PulseAudio support is not available.")); + return; + } + + // If we're still here, PA is available. + logMessage(QLatin1String("PulseAudio support enabled")); + + // Now we connect for real using a proper main loop that we can forget + // all about processing. + s_mainloop = pa_glib_mainloop_new(NULL); + Q_ASSERT(s_mainloop); + pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop); + + s_context = pa_context_new(api, "libphonon"); + // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required + if (pa_context_connect(s_context, NULL, static_cast<pa_context_flags_t>(0), 0) >= 0) + pa_context_set_state_callback(s_context, &context_state_callback, NULL); +#endif +} + +PulseSupport::~PulseSupport() +{ +#ifdef HAVE_PULSEAUDIO + if (s_context) { + pa_context_disconnect(s_context); + s_context = NULL; + } + + if (s_mainloop) { + pa_glib_mainloop_free(s_mainloop); + s_mainloop = NULL; + } +#endif +} + +bool PulseSupport::isActive() +{ +#ifdef HAVE_PULSEAUDIO + return mEnabled && s_pulseActive; +#else + return false; +#endif +} + +void PulseSupport::enable(bool enabled) +{ + mEnabled = enabled; +} + +QList<int> PulseSupport::objectDescriptionIndexes(ObjectDescriptionType type) const +{ + QList<int> list; + + if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType) + return list; + +#ifdef HAVE_PULSEAUDIO + if (s_pulseActive) { + switch (type) { + + case AudioOutputDeviceType: { + QMap<QString, int>::iterator it; + for (it = s_outputDeviceIndexes.begin(); it != s_outputDeviceIndexes.end(); ++it) { + list.append(*it); + } + break; + } + case AudioCaptureDeviceType: { + QMap<QString, int>::iterator it; + for (it = s_captureDeviceIndexes.begin(); it != s_captureDeviceIndexes.end(); ++it) { + list.append(*it); + } + break; + } + default: + break; + } + } +#endif + + return list; +} + +QHash<QByteArray, QVariant> PulseSupport::objectDescriptionProperties(ObjectDescriptionType type, int index) const +{ + QHash<QByteArray, QVariant> ret; + + if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType) + return ret; + +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(index); +#else + if (s_pulseActive) { + switch (type) { + + case AudioOutputDeviceType: + Q_ASSERT(s_outputDevices.contains(index)); + ret = s_outputDevices[index].properties; + break; + + case AudioCaptureDeviceType: + Q_ASSERT(s_captureDevices.contains(index)); + ret = s_captureDevices[index].properties; + break; + + default: + break; + } + } +#endif + + return ret; +} + +QList<int> PulseSupport::objectIndexesByCategory(ObjectDescriptionType type, Category category) const +{ + QList<int> ret; + + if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType) + return ret; + +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); +#else + if (s_pulseActive) { + switch (type) { + + case AudioOutputDeviceType: + if (s_outputDevicePriorities.contains(category)) + ret = s_outputDevicePriorities[category].values(); + break; + + case AudioCaptureDeviceType: + if (s_captureDevicePriorities.contains(category)) + ret = s_captureDevicePriorities[category].values(); + break; + + default: + break; + } + } +#endif + + return ret; +} + +#ifdef HAVE_PULSEAUDIO +static void setDevicePriority(Category category, QStringList list) +{ + QString role = s_roleCategoryMap.key(category); + if (role.isEmpty()) + return; + + logMessage(QString::fromLatin1("Reindexing %1: %2").arg(role).arg(list.join(QLatin1String(", ")))); + + char **devices; + devices = pa_xnew(char *, list.size()+1); + int i = 0; + foreach (QString str, list) { + devices[i++] = pa_xstrdup(str.toUtf8().constData()); + } + devices[list.size()] = NULL; + +#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER + pa_operation *o; + if (!(o = pa_ext_device_manager_reorder_devices_for_role(s_context, role.toUtf8().constData(), (const char**)devices, NULL, NULL))) + logMessage(QString("pa_ext_device_manager_reorder_devices_for_role() failed")); + else + pa_operation_unref(o); +#endif + + for (i = 0; i < list.size(); ++i) + pa_xfree(devices[i]); + pa_xfree(devices); +} +#endif + +void PulseSupport::setOutputDevicePriorityForCategory(Category category, QList<int> order) +{ +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); + Q_UNUSED(order); +#else + QStringList list; + QList<int>::iterator it; + + for (it = order.begin(); it != order.end(); ++it) { + if (s_outputDevices.contains(*it)) { + list << s_outputDeviceIndexes.key(*it); + } + } + setDevicePriority(category, list); +#endif +} + +void PulseSupport::setCaptureDevicePriorityForCategory(Category category, QList<int> order) +{ +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); + Q_UNUSED(order); +#else + QStringList list; + QList<int>::iterator it; + + for (it = order.begin(); it != order.end(); ++it) { + if (s_captureDevices.contains(*it)) { + list << s_captureDeviceIndexes.key(*it); + } + } + setDevicePriority(category, list); +#endif +} + +void PulseSupport::setStreamPropList(Category category, QString streamUuid) +{ +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); + Q_UNUSED(streamUuid); +#else + QString role = s_roleCategoryMap.key(category); + if (role.isEmpty()) + return; + + logMessage(QString::fromLatin1("Setting role to %1 for streamindex %2").arg(role).arg(streamUuid)); + setenv("PULSE_PROP_media.role", role.toLatin1().constData(), 1); + setenv("PULSE_PROP_phonon.streamid", streamUuid.toLatin1().constData(), 1); +#endif +} + +void PulseSupport::emitObjectDescriptionChanged(ObjectDescriptionType type) +{ + emit objectDescriptionChanged(type); +} + +void PulseSupport::emitUsingDevice(QString streamUuid, int device) +{ + emit usingDevice(streamUuid, device); +} + +bool PulseSupport::setOutputDevice(QString streamUuid, int device) { +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(streamUuid); + Q_UNUSED(device); + return false; +#else + if (s_outputDevices.size() < 2) + return true; + + if (!s_outputDevices.contains(device)) { + logMessage(QString::fromLatin1("Attempting to set Output Device for invalid device id %1.").arg(device)); + return false; + } + const QVariant var = s_outputDevices[device].properties["name"]; + logMessage(QString::fromLatin1("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid)); + + // Attempt to look up the pulse stream index. + if (s_outputStreamIndexMap.contains(streamUuid) && s_outputStreamIndexMap[streamUuid] != PA_INVALID_INDEX) { + logMessage(QLatin1String("... Found in map. Moving now")); + + uint32_t pulse_device_index = s_outputDevices[device].pulseIndex; + uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid]; + + logMessage(QString::fromLatin1("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); + + /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. + pa_operation* o; + if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { + logMessage(QLatin1String("pa_context_move_sink_input_by_index() failed")); + return false; + } + pa_operation_unref(o); + } else { + logMessage(QLatin1String("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); + } + return true; +#endif +} + +bool PulseSupport::setCaptureDevice(QString streamUuid, int device) { +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(streamUuid); + Q_UNUSED(device); + return false; +#else + if (s_captureDevices.size() < 2) + return true; + + if (!s_captureDevices.contains(device)) { + logMessage(QString::fromLatin1("Attempting to set Capture Device for invalid device id %1.").arg(device)); + return false; + } + const QVariant var = s_captureDevices[device].properties["name"]; + logMessage(QString::fromLatin1("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid)); + + // Attempt to look up the pulse stream index. + if (s_captureStreamIndexMap.contains(streamUuid) && s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) { + logMessage(QString::fromLatin1("... Found in map. Moving now")); + + uint32_t pulse_device_index = s_captureDevices[device].pulseIndex; + uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid]; + + logMessage(QString::fromLatin1("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); + + /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. + pa_operation* o; + if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { + logMessage(QString::fromLatin1("pa_context_move_source_output_by_index() failed")); + return false; + } + pa_operation_unref(o); + } else { + logMessage(QString::fromLatin1("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); + } + return true; +#endif +} + +void PulseSupport::clearStreamCache(QString streamUuid) { +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(streamUuid); + return; +#else + logMessage(QString::fromLatin1("Clearing stream cache for stream %1").arg(streamUuid)); + s_outputStreamIndexMap.remove(streamUuid); + s_captureStreamIndexMap.remove(streamUuid); +#endif +} + +} // namespace Phonon + +QT_END_NAMESPACE + +#include "moc_pulsesupport.cpp" + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/pulsesupport.h b/src/3rdparty/phonon/phonon/pulsesupport.h new file mode 100644 index 0000000..c38bece --- /dev/null +++ b/src/3rdparty/phonon/phonon/pulsesupport.h @@ -0,0 +1,78 @@ +/* This file is part of the KDE project + Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_PULSESUPPORT_H +#define PHONON_PULSESUPPORT_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include "objectdescription.h" + +#include <QtCore/QtGlobal> +#include <QtCore/QSet> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class PHONON_EXPORT PulseSupport : public QObject + { + Q_OBJECT + public: + static PulseSupport* getInstance(); + static void shutdown(); + + bool isActive(); + void enable(bool enabled = true); + + QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const; + QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const; + QList<int> objectIndexesByCategory(ObjectDescriptionType type, Category category) const; + + void setOutputDevicePriorityForCategory(Category category, QList<int> order); + void setCaptureDevicePriorityForCategory(Category category, QList<int> order); + + void setStreamPropList(Category category, QString streamUuid); + void emitObjectDescriptionChanged(ObjectDescriptionType); + void emitUsingDevice(QString streamUuid, int device); + + bool setOutputDevice(QString streamUuid, int device); + bool setCaptureDevice(QString streamUuid, int device); + void clearStreamCache(QString streamUuid); + + signals: + void objectDescriptionChanged(ObjectDescriptionType); + void usingDevice(QString streamUuid, int device); + + private: + PulseSupport(); + ~PulseSupport(); + + bool mEnabled; + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_PULSESUPPORT_H diff --git a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h new file mode 100644 index 0000000..f25b15e --- /dev/null +++ b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h @@ -0,0 +1,94 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_QSETTINGSGROUP_P_H +#define PHONON_QSETTINGSGROUP_P_H + +#include <QtCore/QSettings> +#include <QtCore/QString> +#include <QtCore/QVariant> + +#ifndef QT_NO_PHONON_SETTINGSGROUP + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +class QSettingsGroup +{ + public: + inline QSettingsGroup(QSettings *settings, const QString &name) + : m_mutableSettings(settings), + m_settings(settings), + m_group(name + QLatin1Char('/')) + { + } + + inline QSettingsGroup(const QSettings *settings, const QString &name) + : m_mutableSettings(0), + m_settings(settings), + m_group(name + QLatin1Char('/')) + { + } + + template<typename T> + inline T value(const QString &key, const T &def) const + { + return qvariant_cast<T>(value(key, QVariant::fromValue(def))); + } + + inline QVariant value(const QString &key, const QVariant &def) const + { + return m_settings->value(m_group + key, def); + } + + template<typename T> + inline void setValue(const QString &key, const T &value) + { + Q_ASSERT(m_mutableSettings); + m_mutableSettings->setValue(m_group + key, QVariant::fromValue(value)); + } + + inline void removeEntry(const QString &key) + { + Q_ASSERT(m_mutableSettings); + m_mutableSettings->remove(m_group + key); + } + + inline bool hasKey(const QString &key) const + { + return m_settings->contains(m_group + key); + } + + private: + QSettings *const m_mutableSettings; + const QSettings *const m_settings; + QString m_group; +}; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER +#endif //QT_NO_PHONON_SETTINGSGROUP + +#endif // PHONON_QSETTINGSGROUP_P_H diff --git a/src/3rdparty/phonon/phonon/seekslider.cpp b/src/3rdparty/phonon/phonon/seekslider.cpp new file mode 100644 index 0000000..b5b25f0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/seekslider.cpp @@ -0,0 +1,263 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "seekslider.h" +#include "seekslider_p.h" +#include "mediaobject.h" +#include "phonondefs_p.h" + +#include <QtGui/QMouseEvent> +#include <QtGui/QApplication> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_SEEKSLIDER + +namespace Phonon +{ + +SeekSlider::SeekSlider(QWidget *parent) + : QWidget(parent) + , k_ptr(new SeekSliderPrivate(this)) +{ + K_D(SeekSlider); + connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_seek(int))); +} + +SeekSlider::SeekSlider(MediaObject *mo, QWidget *parent) + : QWidget(parent) + , k_ptr(new SeekSliderPrivate(this)) +{ + K_D(SeekSlider); + connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_seek(int))); + setMediaObject(mo); +} + +/*SeekSlider::SeekSlider(SeekSliderPrivate &_d, QWidget *parent) + : QWidget(parent) + , k_ptr(&_d) +{ +} */ + +SeekSlider::~SeekSlider() +{ + delete k_ptr; +} + +void SeekSlider::setMediaObject(MediaObject *media) +{ + K_D(SeekSlider); + if (d->media) { + disconnect(d->media, 0, this, 0); + } + d->media = media; + + if (media) { + connect(media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), + SLOT(_k_stateChanged(Phonon::State))); + connect(media, SIGNAL(totalTimeChanged(qint64)), SLOT(_k_length(qint64))); + connect(media, SIGNAL(tick(qint64)), SLOT(_k_tick(qint64))); + connect(media, SIGNAL(seekableChanged(bool)), SLOT(_k_seekableChanged(bool))); + connect(media, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)), SLOT(_k_currentSourceChanged())); + d->_k_stateChanged(media->state()); + d->_k_seekableChanged(media->isSeekable()); + d->_k_length(media->totalTime()); + } else { + d->_k_stateChanged(Phonon::StoppedState); + d->_k_seekableChanged(false); + } +} + +MediaObject *SeekSlider::mediaObject() const +{ + K_D(const SeekSlider); + return d->media; +} + +void SeekSliderPrivate::_k_seek(int msec) +{ + if (!ticking && media) { + media->seek(msec); + } +} + +void SeekSliderPrivate::_k_tick(qint64 msec) +{ + ticking = true; + slider.setValue(msec); + ticking = false; +} + +void SeekSliderPrivate::_k_length(qint64 msec) +{ + ticking = true; + slider.setRange(0, msec); + ticking = false; +} + +void SeekSliderPrivate::_k_seekableChanged(bool isSeekable) +{ + if (!isSeekable || !media) { + setEnabled(false); + } else { + switch (media->state()) { + case Phonon::PlayingState: + if (media->tickInterval() == 0) { + // if the tick signal is not enabled the slider is useless + // set the tickInterval to some common value + media->setTickInterval(350); + } + case Phonon::BufferingState: + case Phonon::PausedState: + setEnabled(true); + break; + case Phonon::StoppedState: + case Phonon::LoadingState: + case Phonon::ErrorState: + setEnabled(false); + ticking = true; + slider.setValue(0); + ticking = false; + break; + } + } +} + +void SeekSliderPrivate::_k_currentSourceChanged() +{ + //this releases the mouse and makes the seek slider stop seeking if the current source has changed + QMouseEvent event(QEvent::MouseButtonRelease, QPoint(), Qt::LeftButton, 0, 0); + QApplication::sendEvent(&slider, &event); +} + +void SeekSliderPrivate::setEnabled(bool x) +{ + slider.setEnabled(x); + iconLabel.setPixmap(icon.pixmap(iconSize, x ? QIcon::Normal : QIcon::Disabled)); +} + +void SeekSliderPrivate::_k_stateChanged(State newstate) +{ + if (!media || !media->isSeekable()) { + setEnabled(false); + return; + } + switch (newstate) { + case Phonon::PlayingState: + if (media->tickInterval() == 0) { + // if the tick signal is not enabled the slider is useless + // set the tickInterval to some common value + media->setTickInterval(350); + } + case Phonon::BufferingState: + case Phonon::PausedState: + setEnabled(true); + break; + case Phonon::StoppedState: + case Phonon::LoadingState: + case Phonon::ErrorState: + setEnabled(false); + ticking = true; + slider.setValue(0); + ticking = false; + break; + } +} + +bool SeekSlider::hasTracking() const +{ + return k_ptr->slider.hasTracking(); +} + +void SeekSlider::setTracking(bool tracking) +{ + k_ptr->slider.setTracking(tracking); +} + +int SeekSlider::pageStep() const +{ + return k_ptr->slider.pageStep(); +} + +void SeekSlider::setPageStep(int milliseconds) +{ + k_ptr->slider.setPageStep(milliseconds); +} + +int SeekSlider::singleStep() const +{ + return k_ptr->slider.singleStep(); +} + +void SeekSlider::setSingleStep(int milliseconds) +{ + k_ptr->slider.setSingleStep(milliseconds); +} + +bool SeekSlider::isIconVisible() const +{ + K_D(const SeekSlider); + return d->iconLabel.isVisible(); +} + +void SeekSlider::setIconVisible(bool vis) +{ + K_D(SeekSlider); + d->iconLabel.setVisible(vis); +} + +Qt::Orientation SeekSlider::orientation() const +{ + return k_ptr->slider.orientation(); +} + +void SeekSlider::setOrientation(Qt::Orientation o) +{ + K_D(SeekSlider); + Qt::Alignment align = (o == Qt::Horizontal ? Qt::AlignVCenter : Qt::AlignHCenter); + d->layout.setAlignment(&d->iconLabel, align); + d->layout.setAlignment(&d->slider, align); + d->layout.setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom); + d->slider.setOrientation(o); +} + +QSize SeekSlider::iconSize() const +{ + return k_ptr->iconSize; +} + +void SeekSlider::setIconSize(const QSize &iconSize) +{ + K_D(SeekSlider); + d->iconSize = iconSize; + d->iconLabel.setPixmap(d->icon.pixmap(d->iconSize, d->slider.isEnabled() ? QIcon::Normal : QIcon::Disabled)); +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_SEEKSLIDER + +QT_END_NAMESPACE + +#include "moc_seekslider.cpp" + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/seekslider.h b/src/3rdparty/phonon/phonon/seekslider.h new file mode 100644 index 0000000..0005029 --- /dev/null +++ b/src/3rdparty/phonon/phonon/seekslider.h @@ -0,0 +1,157 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_UI_SEEKSLIDER_H +#define PHONON_UI_SEEKSLIDER_H + +#include "phonon_export.h" +#include "phonondefs.h" +#include "phononnamespace.h" +#include <QtGui/QWidget> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_SEEKSLIDER + +namespace Phonon +{ +class MediaObject; + +class SeekSliderPrivate; + +/** \class SeekSlider seekslider.h Phonon/SeekSlider + * \short Widget providing a slider for seeking in MediaObject objects. + * + * \ingroup PhononWidgets + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT SeekSlider : public QWidget +{ + Q_OBJECT + K_DECLARE_PRIVATE(SeekSlider) + /** + * This property holds whether the icon next to the slider is visible. + * + * By default the icon is visible if the platform provides an icon; else + * it's hidden. + */ + Q_PROPERTY(bool iconVisible READ isIconVisible WRITE setIconVisible) + + /** + * This property holds whether slider tracking is enabled. + * + * If tracking is enabled (the default), the media seeks + * while the slider is being dragged. If tracking is + * disabled, the media seeks only when the user + * releases the slider. + */ + Q_PROPERTY(bool tracking READ hasTracking WRITE setTracking) + + /** + * This property holds the page step. + * + * The larger of two natural steps that a slider provides and + * typically corresponds to the user pressing PageUp or PageDown. + * + * Defaults to 5 seconds. + */ + Q_PROPERTY(int pageStep READ pageStep WRITE setPageStep) + + /** + * This property holds the single step. + * + * The smaller of two natural steps that a slider provides and + * typically corresponds to the user pressing an arrow key. + * + * Defaults to 0.5 seconds. + */ + Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep) + + /** + * This property holds the orientation of the slider. + * + * The orientation must be Qt::Vertical or Qt::Horizontal (the default). + */ + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) + + /** + * \brief the icon size used for the mute button/icon. + * + * The default size is defined by the GUI style. + */ + Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) + + public: + /** + * Constructs a seek slider widget with the given \p parent. + */ + explicit SeekSlider(QWidget *parent = 0); + explicit SeekSlider(MediaObject *media, QWidget *parent = 0); + + /** + * Destroys the seek slider. + */ + ~SeekSlider(); + + bool hasTracking() const; + void setTracking(bool tracking); + int pageStep() const; + void setPageStep(int milliseconds); + int singleStep() const; + void setSingleStep(int milliseconds); + Qt::Orientation orientation() const; + bool isIconVisible() const; + QSize iconSize() const; + MediaObject *mediaObject() const; + + public Q_SLOTS: + void setOrientation(Qt::Orientation); + void setIconVisible(bool); + void setIconSize(const QSize &size); + + /** + * Sets the media object to be controlled by this slider. + */ + void setMediaObject(MediaObject *); + + protected: + SeekSliderPrivate *const k_ptr; + + private: + Q_PRIVATE_SLOT(k_func(), void _k_stateChanged(Phonon::State)) + Q_PRIVATE_SLOT(k_func(), void _k_seek(int)) + Q_PRIVATE_SLOT(k_func(), void _k_tick(qint64)) + Q_PRIVATE_SLOT(k_func(), void _k_length(qint64)) + Q_PRIVATE_SLOT(k_func(), void _k_seekableChanged(bool)) + Q_PRIVATE_SLOT(k_func(), void _k_currentSourceChanged()) +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_SEEKSLIDER + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // PHONON_UI_SEEKSLIDER_H diff --git a/src/3rdparty/phonon/phonon/seekslider_p.h b/src/3rdparty/phonon/phonon/seekslider_p.h new file mode 100644 index 0000000..911ab25 --- /dev/null +++ b/src/3rdparty/phonon/phonon/seekslider_p.h @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef SEEKSLIDER_P_H +#define SEEKSLIDER_P_H + +#include "seekslider.h" +#include "swiftslider_p.h" +#include <QtGui/QBoxLayout> +#include <QtGui/QLabel> +#include <QtGui/QPixmap> +#include <QtGui/QIcon> +#include <QtGui/QStyle> +#include "factory_p.h" +#include <QtCore/QPointer> +#include "platform_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_SEEKSLIDER + +namespace Phonon +{ +class MediaObject; +class SeekSliderPrivate +{ + Q_DECLARE_PUBLIC(SeekSlider) + protected: + SeekSliderPrivate(SeekSlider *parent) + : layout(QBoxLayout::LeftToRight, parent), + slider(Qt::Horizontal, parent), + iconLabel(parent), + ticking(false) +#ifndef QT_NO_PHONON_PLATFORMPLUGIN + ,icon(Platform::icon(QLatin1String("player-time"), parent->style())) +#endif //QT_NO_PHONON_PLATFORMPLUGIN + { + const int e = parent->style()->pixelMetric(QStyle::PM_ButtonIconSize); + iconSize = QSize(e, e); + + slider.setPageStep(5000); // 5 sec + slider.setSingleStep(500); // 0.5 sec + + layout.setMargin(0); + layout.setSpacing(2); + layout.addWidget(&iconLabel, 0, Qt::AlignVCenter); + layout.addWidget(&slider, 0, Qt::AlignVCenter); + + setEnabled(false); + + if (icon.isNull()) { + iconLabel.setVisible(false); + } + } + + SeekSlider *q_ptr; + + private: + void setEnabled(bool); + void _k_stateChanged(Phonon::State); + void _k_seek(int); + void _k_tick(qint64); + void _k_length(qint64); + void _k_seekableChanged(bool); + void _k_currentSourceChanged(); + + QBoxLayout layout; + SwiftSlider slider; + QLabel iconLabel; + QPointer<MediaObject> media; + bool ticking; + QIcon icon; + QSize iconSize; +}; +} // namespace Phonon + +#endif //QT_NO_PHONON_SEEKSLIDER + +QT_END_NAMESPACE + +#endif // SEEKSLIDER_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/stream-thoughts b/src/3rdparty/phonon/phonon/stream-thoughts new file mode 100644 index 0000000..5fb6711 --- /dev/null +++ b/src/3rdparty/phonon/phonon/stream-thoughts @@ -0,0 +1,72 @@ +there are two different kind of streams: 1. media files 2. live radio/television + +The difference cannot reliably be determined by the backend so the application has to tell the +frontend. + +This is the expected behaviour: +1. media files +============== +function | prev. state | action | new state +---------+-------------+----------------------------------------------------------------+---------- +ctor | | | Loading +---------+-------------+----------------------------------------------------------------+---------- +setUrl | Loading | refill buffers | Loading + | Stopped | refill buffers | Loading +---------+-------------+----------------------------------------------------------------+---------- +play | Loading | continue buffering | Buffering + | Stopped | start playing | Playing + | Buffering | continue buffering | Buffering + | Playing | | Playing + | Paused | continue playback | Playing +---------+-------------+----------------------------------------------------------------+---------- +pause | Loading | | Loading + | Stopped | | Stopped + | Buffering | continue buffering | Paused + | Playing | pause output and fill buffers to the max | Paused + | Paused | | Paused +---------+-------------+----------------------------------------------------------------+---------- +stop | Loading | | Loading + | Stopped | | Stopped + | Buffering | restart buffering from the beginning of the file | Loading + | Playing | stop output and refill buffers from the beginning of the file | Loading + | Paused | restart buffering from the beginning of the file | Loading + +events +function | prev. state | event | new state +---------+-------------+----------------------------------------------------------------+---------- + | Buffering | when the buffers are filled start playing | Playing + | Loading | when buffers are filled | Stopped + + + +2. live stream +============== +function | prev. state | action | new state +---------+-------------+----------------------------------------------------------------+---------- +ctor | | | Loading +---------+-------------+----------------------------------------------------------------+---------- +setUrl | Loading | | Stopped + | Stopped | | Stopped +---------+-------------+----------------------------------------------------------------+---------- +play | Loading | | Error + | Stopped | start buffering | Buffering + | Buffering | continue buffering | Buffering + | Playing | | Playing + | Paused | continue playback | Playing +---------+-------------+----------------------------------------------------------------+---------- +pause | Loading | | Error + | Stopped | | Stopped + | Buffering | continue buffering | Paused + | Playing | pause output and fill (ring-)buffers to the max | Paused + | Paused | | Paused +---------+-------------+----------------------------------------------------------------+---------- +stop | Loading | | Error + | Stopped | | Stopped + | Buffering | clear buffers | Stopped + | Playing | stop output and clear buffers | Stopped + | Paused | clear buffers | Stopped + +events +function | prev. state | event | new state +---------+-------------+----------------------------------------------------------------+---------- + | Buffering | when the buffers are filled start playing | Playing diff --git a/src/3rdparty/phonon/phonon/streaminterface.cpp b/src/3rdparty/phonon/phonon/streaminterface.cpp new file mode 100644 index 0000000..666cb1e --- /dev/null +++ b/src/3rdparty/phonon/phonon/streaminterface.cpp @@ -0,0 +1,114 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "streaminterface.h" +#include "streaminterface_p.h" +#include "abstractmediastream.h" +#include "abstractmediastream_p.h" +#include "mediasource_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +namespace Phonon +{ + +StreamInterface::StreamInterface() + : d(new StreamInterfacePrivate) +{ + d->q = this; +} + +StreamInterface::~StreamInterface() +{ + if (d->connected) { + AbstractMediaStreamPrivate *dd = d->mediaSource.stream()->d_func(); + dd->setStreamInterface(0); + } + delete d; +} + +void StreamInterface::connectToSource(const MediaSource &mediaSource) +{ + Q_ASSERT(!d->connected); + d->connected = true; + d->mediaSource = mediaSource; + Q_ASSERT(d->mediaSource.type() == MediaSource::Stream); + Q_ASSERT(d->mediaSource.stream()); + AbstractMediaStreamPrivate *dd = d->mediaSource.stream()->d_func(); + dd->setStreamInterface(this); + d->mediaSource.stream()->reset(); +} + +void StreamInterfacePrivate::disconnectMediaStream() +{ + Q_ASSERT(connected); + connected = false; + + // if mediaSource has autoDelete set then it will delete the AbstractMediaStream again who's + // destructor is calling us right now + mediaSource.setAutoDelete(false); + + mediaSource = MediaSource(); + q->endOfData(); + q->setStreamSeekable(false); +} + +void StreamInterface::needData() +{ + if (d->mediaSource.type() == MediaSource::Stream) { + d->mediaSource.stream()->needData(); + } +} + +void StreamInterface::enoughData() +{ + Q_ASSERT(d->connected); + if (d->mediaSource.type() == MediaSource::Stream) { + d->mediaSource.stream()->enoughData(); + } +} + +void StreamInterface::seekStream(qint64 offset) +{ + Q_ASSERT(d->connected); + if (d->mediaSource.type() == MediaSource::Stream) { + d->mediaSource.stream()->seekStream(offset); + } +} + +void StreamInterface::reset() +{ + Q_ASSERT(d->connected); + if (d->mediaSource.type() == MediaSource::Stream) { + d->mediaSource.stream()->reset(); + } +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE + + diff --git a/src/3rdparty/phonon/phonon/streaminterface.h b/src/3rdparty/phonon/phonon/streaminterface.h new file mode 100644 index 0000000..67df05d --- /dev/null +++ b/src/3rdparty/phonon/phonon/streaminterface.h @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_STREAMINTERFACE_H +#define PHONON_STREAMINTERFACE_H + +#include "phonon_export.h" +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +namespace Phonon +{ +class StreamInterfacePrivate; +class MediaSource; + +/** \class StreamInterface streaminterface.h Phonon/StreamInterface + * \brief Backend interface to handle media streams (AbstractMediaStream). + * + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT StreamInterface +{ + friend class StreamInterfacePrivate; + friend class AbstractMediaStreamPrivate; + public: + virtual ~StreamInterface(); + /** + * Called by the application to send a chunk of (encoded) media data. + * + * It is recommended to keep the QByteArray object until the data is consumed so that no + * memcopy is needed. + */ + virtual void writeData(const QByteArray &data) = 0; + /** + * Called when no more media data is available and writeData will not be called anymore. + */ + virtual void endOfData() = 0; + /** + * Called at the start of the stream to tell how many bytes will be sent through writeData + * (if no seeks happen, of course). If this value is negative the stream size cannot be + * determined (might be a "theoretically infinite" stream - like webradio). + */ + virtual void setStreamSize(qint64 newSize) = 0; + /** + * Tells whether the stream is seekable. + */ + virtual void setStreamSeekable(bool s) = 0; + + /** + * Call this function from the constructor of your StreamInterface implementation (or as + * soon as you get the MediaSource object). This will connect your object to the + * AbstractMediaStream object. Only after the connection is done will the following + * functions have an effect. + */ + void connectToSource(const MediaSource &mediaSource); + + /** + * Call this function to tell the AbstractMediaStream that you need more data. The data will + * arrive through writeData. Don't rely on writeData getting called from needData, though + * some AbstractMediaStream implementations might do so. + * + * Depending on the buffering you need you either treat needData as a replacement for a + * read call like QIODevice::read, or you start calling needData whenever your buffer + * reaches a certain lower threshold. + */ + void needData(); + + /** + * Call this function to tell the AbstractMediaStream that you have enough data in your + * buffer and that it should pause calling writeData if possible. + */ + void enoughData(); + + /** + * If the stream is seekable, calling this function will make the next call to writeData + * pass data that starts at the byte offset \p seekTo. + */ + void seekStream(qint64 seekTo); + + /** + * Resets the AbstractMediaStream. E.g. this can be useful for non-seekable streams to start + * over again. + */ + void reset(); + + protected: + StreamInterface(); + + StreamInterfacePrivate *const d; +}; +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::StreamInterface, "StreamInterface1.phonon.kde.org") + +#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_STREAMINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/streaminterface_p.h b/src/3rdparty/phonon/phonon/streaminterface_p.h new file mode 100644 index 0000000..426c58d --- /dev/null +++ b/src/3rdparty/phonon/phonon/streaminterface_p.h @@ -0,0 +1,59 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef STREAMINTERFACE_P_H +#define STREAMINTERFACE_P_H + +#include "streaminterface.h" +#include "mediasource.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + +namespace Phonon +{ +class StreamInterfacePrivate +{ + friend class StreamInterface; + public: + void disconnectMediaStream(); + + protected: + inline StreamInterfacePrivate() + : connected(false) + { + } + + StreamInterface *q; + MediaSource mediaSource; + bool connected; +}; + +} // namespace Phonon + +#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM + +QT_END_NAMESPACE + +#endif // STREAMINTERFACE_P_H +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/swiftslider.cpp b/src/3rdparty/phonon/phonon/swiftslider.cpp new file mode 100644 index 0000000..1e274aa --- /dev/null +++ b/src/3rdparty/phonon/phonon/swiftslider.cpp @@ -0,0 +1,103 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "swiftslider_p.h" + +#include <QtGui/QMouseEvent> +#include <QtGui/QStyle> +#include <QtGui/QStyleOption> + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER) + +namespace Phonon +{ + +SwiftSlider::SwiftSlider(Qt::Orientation orientation, QWidget * parent) + : QSlider(orientation, parent) +{ +} + +SwiftSlider::~SwiftSlider() +{ +} + +// Function copied from qslider.cpp +inline int SwiftSlider::pick(const QPoint &pt) const +{ + return orientation() == Qt::Horizontal ? pt.x() : pt.y(); +} + +// Function copied from qslider.cpp and modified to make it compile +int SwiftSlider::pixelPosToRangeValue(int pos) const +{ + QStyleOptionSlider opt; + initStyleOption(&opt); + QRect gr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this); + QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); + int sliderMin, sliderMax, sliderLength; + + if (orientation() == Qt::Horizontal) { + sliderLength = sr.width(); + sliderMin = gr.x(); + sliderMax = gr.right() - sliderLength + 1; + } else { + sliderLength = sr.height(); + sliderMin = gr.y(); + sliderMax = gr.bottom() - sliderLength + 1; + } + return QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin, + sliderMax - sliderMin, opt.upsideDown); +} + +// Based on code from qslider.cpp +void SwiftSlider::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + QStyleOptionSlider opt; + initStyleOption(&opt); + const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); + const QPoint center = sliderRect.center() - sliderRect.topLeft(); + // to take half of the slider off for the setSliderPosition call we use the center - topLeft + + if (!sliderRect.contains(event->pos())) { + event->accept(); + + setSliderPosition(pixelPosToRangeValue(pick(event->pos() - center))); + triggerAction(SliderMove); + setRepeatAction(SliderNoAction); + } else { + QSlider::mousePressEvent(event); + } + } else { + QSlider::mousePressEvent(event); + } +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE + +#include "moc_swiftslider_p.cpp" diff --git a/src/3rdparty/phonon/phonon/swiftslider_p.h b/src/3rdparty/phonon/phonon/swiftslider_p.h new file mode 100644 index 0000000..b063b47 --- /dev/null +++ b/src/3rdparty/phonon/phonon/swiftslider_p.h @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef SWIFTSLIDER_H +#define SWIFTSLIDER_H + +#include <QtGui/QSlider> + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER) + +namespace Phonon +{ + +/** \class SwiftSlider swiftslider_p.h phonon/SwiftSlider + * \short Modified QSlider that allows sudden/quick moves instead of stepped moves ("Click'n'Go" QSlider) + * + * This is an internal class used by SeekSlider and VolumeSlider. + * + * Ricardo Villalba, the original author of MySlider.cpp (from the SMPlayer project) + * gave his permission for the inclusion of this code inside Phonon by + * switching MySlider.cpp to the LGPLv2.1+ license. + * See http://smplayer.svn.sourceforge.net/viewvc/smplayer/smplayer/trunk/src/myslider.cpp?revision=2406&view=markup + * + * The original discussion about a "Click'n'Go QSlider": http://lists.trolltech.com/qt-interest/2006-11/msg00363.html + * + * \ingroup PhononWidgets + */ +class SwiftSlider : public QSlider +{ + Q_OBJECT +public: + SwiftSlider(Qt::Orientation orientation, QWidget * parent); + ~SwiftSlider(); + +private: + void mousePressEvent(QMouseEvent *event); + inline int pick(const QPoint &pt) const; + int pixelPosToRangeValue(int pos) const; +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE + +#endif //SWIFTSLIDER_H diff --git a/src/3rdparty/phonon/phonon/videoplayer.cpp b/src/3rdparty/phonon/phonon/videoplayer.cpp new file mode 100644 index 0000000..8851b05 --- /dev/null +++ b/src/3rdparty/phonon/phonon/videoplayer.cpp @@ -0,0 +1,184 @@ +/* This file is part of the KDE project + Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "videoplayer.h" +#include "mediaobject.h" +#include "audiooutput.h" +#include "videowidget.h" +#include "path.h" +#include <QtGui/QBoxLayout> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEOPLAYER + +namespace Phonon +{ + +class VideoPlayerPrivate +{ + public: + VideoPlayerPrivate() + : player(0) + , aoutput(0) + , voutput(0) {} + + void init(VideoPlayer *q, Phonon::Category category); + + MediaObject *player; + AudioOutput *aoutput; + VideoWidget *voutput; + + MediaSource src; +}; + +void VideoPlayerPrivate::init(VideoPlayer *q, Phonon::Category category) +{ + QVBoxLayout *layout = new QVBoxLayout(q); + layout->setMargin(0); + + aoutput = new AudioOutput(category, q); + + voutput = new VideoWidget(q); + layout->addWidget(voutput); + + player = new MediaObject(q); + Phonon::createPath(player, aoutput); + Phonon::createPath(player, voutput); + + q->connect(player, SIGNAL(finished()), SIGNAL(finished())); +} + +VideoPlayer::VideoPlayer(Phonon::Category category, QWidget *parent) + : QWidget(parent) + , d(new VideoPlayerPrivate) +{ + d->init(this, category); +} + +VideoPlayer::VideoPlayer(QWidget *parent) + : QWidget(parent) + , d(new VideoPlayerPrivate) +{ + d->init(this, Phonon::VideoCategory); +} + +VideoPlayer::~VideoPlayer() +{ + delete d; +} + +MediaObject *VideoPlayer::mediaObject() const +{ + return d->player; +} + +AudioOutput *VideoPlayer::audioOutput() const +{ + return d->aoutput; +} + +VideoWidget *VideoPlayer::videoWidget() const +{ + return d->voutput; +} + +void VideoPlayer::load(const MediaSource &source) +{ + d->player->setCurrentSource(source); +} + +void VideoPlayer::play(const MediaSource &source) +{ + if (source == d->player->currentSource()) { + if (!isPlaying()) + d->player->play(); + return; + } + // new URL + d->player->setCurrentSource(source); + + if (ErrorState == d->player->state()) + return; + + d->player->play(); +} + +void VideoPlayer::play() +{ + d->player->play(); +} + +void VideoPlayer::pause() +{ + d->player->pause(); +} + +void VideoPlayer::stop() +{ + d->player->stop(); +} + +qint64 VideoPlayer::totalTime() const +{ + return d->player->totalTime(); +} + +qint64 VideoPlayer::currentTime() const +{ + return d->player->currentTime(); +} + +void VideoPlayer::seek(qint64 ms) +{ + d->player->seek(ms); +} + +float VideoPlayer::volume() const +{ + return d->aoutput->volume(); +} + +void VideoPlayer::setVolume(float v) +{ + d->aoutput->setVolume(v); +} + +bool VideoPlayer::isPlaying() const +{ + return (d->player->state() == PlayingState); +} + +bool VideoPlayer::isPaused() const +{ + return (d->player->state() == PausedState); +} + +} // namespaces + +#endif //QT_NO_PHONON_VIDEOPLAYER + +QT_END_NAMESPACE + +#include "moc_videoplayer.cpp" + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/videoplayer.h b/src/3rdparty/phonon/phonon/videoplayer.h new file mode 100644 index 0000000..7970f04 --- /dev/null +++ b/src/3rdparty/phonon/phonon/videoplayer.h @@ -0,0 +1,207 @@ +/* This file is part of the KDE project + Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef Phonon_VIDEOPLAYER_H +#define Phonon_VIDEOPLAYER_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include "mediasource.h" +#include <QtGui/QWidget> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEOPLAYER + +namespace Phonon +{ +class VideoPlayerPrivate; +class MediaObject; +class AudioOutput; +class VideoWidget; + +/** \class VideoPlayer videoplayer.h Phonon/VideoPlayer + * \short Playback class for simple tasks. + * + * With %VideoPlayer you can get results quickly and easily. You can do the standard + * playback tasks like play, pause and stop, but also set a playback volume and + * seek (there's no guarantee that the seek will work, though). + * + * Keep in mind that when the %VideoPlayer instance is deleted the playback will + * stop. + * + * A play and forget code example: + * \code + * VideoPlayer *player = new VideoPlayer(parentWidget); + * connect(player, SIGNAL(finished()), player, SLOT(deleteLater())); + * player->play(url); + * \endcode + * + * \ingroup Playback + * \ingroup PhononVideo + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT VideoPlayer : public QWidget +{ + Q_OBJECT + public: + /** + * Constructs a new %VideoPlayer instance. + * + * \param category The category used for the audio output device. + * \param parent The QObject parent. + */ + explicit VideoPlayer(Phonon::Category category, QWidget *parent = 0); + + /** + * Constructs a new video widget with a \p parent + * using Phonon::VideoCategory as its category. + * + * \param parent The QObject parent. + */ + VideoPlayer(QWidget *parent = 0); + + /** + * On destruction the playback is stopped, also the audio output is + * removed so that the desktop mixer will not show the application + * anymore. If you need a persistent audio output don't use + * %VideoPlayer but MediaObject, VideoPath and VideoOutput. + */ + ~VideoPlayer(); + + /** + * Get the total time (in milliseconds) of the file currently being played. + */ + qint64 totalTime() const; + /** + * Get the current time (in milliseconds) of the file currently being played. + */ + qint64 currentTime() const; + /** + * This is the current volume of the output as voltage factor. + * + * 1.0 means 100%, 0.5 means 50% voltage/25% power, 0.0 means 0% + */ + float volume() const; + + /** + * \returns \c true if it is currently playing + * \returns \c false if it is currently stopped or paused + */ + bool isPlaying() const; + /** + * \returns \c true if it is currently paused + * \returns \c false if it is currently playing or stopped + */ + bool isPaused() const; + + /** + * getter for the MediaObject. + */ + MediaObject *mediaObject() const; + + /** + * getter for the AudioOutput. + */ + AudioOutput *audioOutput() const; + + /** + * getter for the VideoWidget. + */ + VideoWidget *videoWidget() const; + + public Q_SLOTS: + /** + * Starts preloading the media data and fill audiobuffers in the + * backend. + * + * When there's already a media playing (or paused) it will be stopped + * (the finished signal will not be emitted). + */ + void load(const Phonon::MediaSource &source); + + /** + * Play the media at the given URL. Starts playback as fast as possible. + * This can take a considerable time depending on the URL and the + * backend. + * + * If you need low latency between calling play() and the sound actually + * starting to play on your output device you need to use MediaObject + * and be able to set the URL before calling play(). Note that + * \code + * audioPlayer->load(url); + * audioPlayer->play(); + * \endcode + * doesn't make a difference: the application should be idle between the + * load and play calls so that the backend can start preloading the + * media and fill audio buffers. + */ + void play(const Phonon::MediaSource &source); + + /** + * Continues playback of a paused media. Restarts playback of a stopped + * media. + */ + void play(); + /** + * Pauses the playback. + */ + void pause(); + /** + * Stops the playback. + */ + void stop(); + + /** + * Seeks to the requested time. Note that the backend is free to ignore + * the seek request if the media source isn't seekable. + * + * \param ms Time in milliseconds from the start of the media. + */ + void seek(qint64 ms); + /** + * Sets the volume of the output as voltage factor. + * + * 1.0 means 100%, 0.5 means 50% voltage/25% power, 0.0 means 0% + */ + void setVolume(float volume); + + Q_SIGNALS: + /** + * This signal is emitted when the playback finished. + */ + void finished(); + + protected: + VideoPlayerPrivate *const d; +}; + +} //namespace Phonon + +#endif //QT_NO_PHONON_VIDEOPLAYER + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // Phonon_VIDEOPLAYER_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/videowidget.cpp b/src/3rdparty/phonon/phonon/videowidget.cpp new file mode 100644 index 0000000..4575dfd --- /dev/null +++ b/src/3rdparty/phonon/phonon/videowidget.cpp @@ -0,0 +1,195 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "videowidget.h" +#include "videowidget_p.h" +#include "videowidgetinterface.h" +#include "factory_p.h" +#include "phonondefs_p.h" +#include "phononnamespace_p.h" + +#include <QtGui/QAction> +#define IFACES4 VideoWidgetInterface44 +#define IFACES0 VideoWidgetInterface, IFACES4 +#define PHONON_INTERFACENAME IFACES0 + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ + +VideoWidget::VideoWidget(QWidget *parent) + : QWidget(parent) + , Phonon::AbstractVideoOutput(*new VideoWidgetPrivate(this)) +{ + K_D(VideoWidget); + d->init(); + d->createBackendObject(); + setMouseTracking(true); +} + + + +VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent) + : QWidget(parent), + Phonon::AbstractVideoOutput(dd) +{ + K_D(VideoWidget); + d->init(); +} + +void VideoWidgetPrivate::init() +{ + Q_Q(VideoWidget); + changeFlags = q->windowFlags() & (Qt::SubWindow | Qt::Window); +} + +void VideoWidget::mouseMoveEvent(QMouseEvent *e) +{ + QWidget::mouseMoveEvent(e); +} + +void VideoWidgetPrivate::createBackendObject() +{ + if (m_backendObject) + return; + Q_Q(VideoWidget); + m_backendObject = Factory::createVideoWidget(q); + if (m_backendObject) { + setupBackendObject(); + } +} + +#define PHONON_CLASSNAME VideoWidget + +PHONON_INTERFACE_GETTER(Phonon::VideoWidget::AspectRatio, aspectRatio, d->aspectRatio) +PHONON_INTERFACE_SETTER(setAspectRatio, aspectRatio, Phonon::VideoWidget::AspectRatio) + +PHONON_INTERFACE_GETTER(Phonon::VideoWidget::ScaleMode, scaleMode, d->scaleMode) +PHONON_INTERFACE_SETTER(setScaleMode, scaleMode, Phonon::VideoWidget::ScaleMode) + +PHONON_INTERFACE_GETTER(qreal, brightness, d->brightness) +PHONON_INTERFACE_SETTER(setBrightness, brightness, qreal) + +PHONON_INTERFACE_GETTER(qreal, contrast, d->contrast) +PHONON_INTERFACE_SETTER(setContrast, contrast, qreal) + +PHONON_INTERFACE_GETTER(qreal, hue, d->hue) +PHONON_INTERFACE_SETTER(setHue, hue, qreal) + +PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation) +PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal) + + +QImage VideoWidget::snapshot() const { + K_D(const VideoWidget); + ConstIface<IFACES4> iface(d); + if(iface) return iface->snapshot(); + return QImage(); // TODO not implemented in VideoInterface +} + + +void VideoWidget::setFullScreen(bool newFullScreen) +{ + pDebug() << Q_FUNC_INFO << newFullScreen; + K_D(VideoWidget); + // TODO: disable screensaver? or should we leave that responsibility to the + // application? + Qt::WindowFlags flags = windowFlags(); + if (newFullScreen) { + if (!isFullScreen()) { + //we only update that value if it is not already fullscreen + d->changeFlags = flags & (Qt::Window | Qt::SubWindow); + flags |= Qt::Window; + flags ^= Qt::SubWindow; + setWindowFlags(flags); +#ifdef Q_WS_X11 + // This works around a bug with Compiz + // as the window must be visible before we can set the state + show(); + raise(); + setWindowState( windowState() | Qt::WindowFullScreen ); // set +#else + setWindowState( windowState() | Qt::WindowFullScreen ); // set + show(); +#endif + } + } else if (isFullScreen()) { + flags ^= (Qt::Window | Qt::SubWindow); //clear the flags... + flags |= d->changeFlags; //then we reset the flags (window and subwindow) + setWindowFlags(flags); + setWindowState( windowState() ^ Qt::WindowFullScreen ); // reset + show(); + } +} + +void VideoWidget::exitFullScreen() +{ + setFullScreen(false); +} + +void VideoWidget::enterFullScreen() +{ + setFullScreen(true); +} + +bool VideoWidgetPrivate::aboutToDeleteBackendObject() +{ + aspectRatio = pINTERFACE_CALL(aspectRatio()); + scaleMode = pINTERFACE_CALL(scaleMode()); + return AbstractVideoOutputPrivate::aboutToDeleteBackendObject(); +} + +void VideoWidgetPrivate::setupBackendObject() +{ + Q_Q(VideoWidget); + Q_ASSERT(m_backendObject); + //AbstractVideoOutputPrivate::setupBackendObject(); + pDebug() << "calling setAspectRatio on the backend " << aspectRatio; + pINTERFACE_CALL(setAspectRatio(aspectRatio)); + pINTERFACE_CALL(setScaleMode(scaleMode)); + + QWidget *w = pINTERFACE_CALL(widget()); + if (w) { + layout.addWidget(w); + q->setSizePolicy(w->sizePolicy()); + w->setMouseTracking(true); + } +} + +bool VideoWidget::event(QEvent *e) +{ + return QWidget::event(e); +} + +} //namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE + +#include "moc_videowidget.cpp" + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/videowidget.h b/src/3rdparty/phonon/phonon/videowidget.h new file mode 100644 index 0000000..804e61a --- /dev/null +++ b/src/3rdparty/phonon/phonon/videowidget.h @@ -0,0 +1,220 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ +#ifndef Phonon_VIDEOWIDGET_H +#define Phonon_VIDEOWIDGET_H + +#include "phonon_export.h" +#include "phonondefs.h" +#include "abstractvideooutput.h" +#include <QtGui/QWidget> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QString; + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ +class AbstractVideoOutput; + class VideoWidgetPrivate; + /** \class VideoWidget videowidget.h Phonon/VideoWidget + * \short Widget to display video. + * + * This widget shows the video signal. + * + * \code + * MediaObject *media = new MediaObject(parent); + * VideoWidget *vwidget = new VideoWidget(parent); + * Phonon::createPath(media, vwidget); + * \endcode + * + * \ingroup PhononVideo + * \ingroup PhononWidgets + * \author Matthias Kretz <kretz@kde.org> + */ + class PHONON_EXPORT VideoWidget : public QWidget, public Phonon::AbstractVideoOutput + { + K_DECLARE_PRIVATE(VideoWidget) + Q_OBJECT + Q_ENUMS(AspectRatio ScaleMode) + /** + * This property holds whether the video is shown using the complete + * screen. + * + * The property differs from QWidget::fullScreen in that it is + * writeable. + * + * By default the widget is not shown in fullScreen. + * + * \warning When switching the video to fullscreen using setFullScreen + * your application loses control over the widget that actually shows + * the video (which is then shown as a toplevel window while your + * application still uses this widget). If you only need to capture key + * events the event forwarding done internally should suffice for your + * needs. If you need to map mouse coordinates or add widgets (that are + * not overlays) you should probably handle fullscreen yourself. + */ + Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen) + /** + * + * Defaults to AspectRatioAuto. + * + * \see AspectRatio + */ + Q_PROPERTY(AspectRatio aspectRatio READ aspectRatio WRITE setAspectRatio) + + /** + * If the size of the widget and the size of the video are not equal. + * The video will be zoomed to fit the widget. The smaller zoom + * (AddBarsScaleMode) adds black bars at the left/right or top/bottom to + * make all of the image visible (default). The bigger zoom (ExpandMode) + * fills the widget completely, keeping all information in one direction + * and leaving parts of the image outside of the widget in the other + * direction. + */ + Q_PROPERTY(ScaleMode scaleMode READ scaleMode WRITE setScaleMode) + + /** + * This property holds brightness of the video. + * + * Default is 0. Acceptable values are in range of -1, 1. + */ + Q_PROPERTY(qreal brightness READ brightness WRITE setBrightness) + /** + * This property holds the contrast of the video. + * + * Default is 0. Acceptable values are in range of -1, 1. + */ + Q_PROPERTY(qreal contrast READ contrast WRITE setContrast) + /** + * This property holds the hue of the video. + * + * Default is 0. Acceptable values are in range of -1, 1. + */ + Q_PROPERTY(qreal hue READ hue WRITE setHue) + /** + * This property holds saturation of the video. + * + * Default is 0. Acceptable values are in range of -1, 1. + */ + Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation) + + public: + /** + * Defines the width:height to be used for the video. + */ + enum AspectRatio + { + /** + * Let the decoder find the aspect ratio automatically from the + * media file (this is the default). + */ + AspectRatioAuto = 0, + /** + * Fits the video into the widget making the aspect ratio depend + * solely on the size of the widget. This way the aspect ratio + * is freely resizeable by the user. + */ + AspectRatioWidget = 1, + /** + * Make width/height == 4/3, which is the old TV size and + * monitor size (1024/768 == 4/3). (4:3) + */ + AspectRatio4_3 = 2, + /** + * Make width/height == 16/9, which is the size of most current + * media. (16:9) + */ + AspectRatio16_9 = 3 +//X /** +//X * Assume that every pixel of the video image needs to be displayed with the same +//X * physical width and height. (1:1 image pixels, not imagewidth +//X * = imageheight) +//X */ +//X AspectRatioSquare = 4, + }; + + enum ScaleMode { + FitInView = 0, + ScaleAndCrop = 1 + }; + + /** + * Constructs a new video widget with a \p parent. + */ + VideoWidget(QWidget *parent = 0); + + AspectRatio aspectRatio() const; + ScaleMode scaleMode() const; + + qreal brightness() const; + qreal contrast() const; + qreal hue() const; + qreal saturation() const; + QImage snapshot() const; + + //TODO: bar colors property + public Q_SLOTS: + void setFullScreen(bool fullscreen); + + /** + * Convenience slot, calling setFullScreen(false) + */ + void exitFullScreen(); + + /** + * Convenience slot, calling setFullScreen(true) + */ + void enterFullScreen(); + + void setAspectRatio(AspectRatio); + void setScaleMode(ScaleMode); + + void setBrightness(qreal value); + void setContrast(qreal value); + void setHue(qreal value); + void setSaturation(qreal value); + + protected: + /** + * \internal + * + * Constructs a new video widget with private data pointer \p d and + * a \p parent. + */ + VideoWidget(VideoWidgetPrivate &d, QWidget *parent); + + void mouseMoveEvent(QMouseEvent *); + bool event(QEvent *); + }; + +} //namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_VIDEOWIDGET_H diff --git a/src/3rdparty/phonon/phonon/videowidget_p.h b/src/3rdparty/phonon/phonon/videowidget_p.h new file mode 100644 index 0000000..3335135 --- /dev/null +++ b/src/3rdparty/phonon/phonon/videowidget_p.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef VIDEOWIDGET_P_H +#define VIDEOWIDGET_P_H + +#include "videowidget.h" +#include "abstractvideooutput_p.h" +#include <QtGui/QBoxLayout> +#include <QtCore/QEvent> +#include <QtCore/QCoreApplication> +#include <QtGui/QPalette> +#include <QtGui/QKeyEvent> +#include <QtCore/QTimer> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ + +class VideoWidgetPrivate : public Phonon::AbstractVideoOutputPrivate +{ + Q_DECLARE_PUBLIC(VideoWidget) + public: + virtual QObject *qObject() { return q_func(); } + protected: + virtual bool aboutToDeleteBackendObject(); + virtual void createBackendObject(); + void setupBackendObject(); + + VideoWidgetPrivate(VideoWidget *parent) + : layout(parent), + aspectRatio(VideoWidget::AspectRatioAuto), + scaleMode(VideoWidget::FitInView), + brightness(0), + contrast(0), + hue(0), + saturation(0) + { + layout.setMargin(0); + } + + QHBoxLayout layout; + VideoWidget::AspectRatio aspectRatio; + VideoWidget::ScaleMode scaleMode; + Qt::WindowFlags changeFlags; + + qreal brightness; + qreal contrast; + qreal hue; + qreal saturation; + + private: + void init(); +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE +#endif // VIDEOWIDGET_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/videowidgetinterface.h b/src/3rdparty/phonon/phonon/videowidgetinterface.h new file mode 100644 index 0000000..0c33956 --- /dev/null +++ b/src/3rdparty/phonon/phonon/videowidgetinterface.h @@ -0,0 +1,78 @@ +/* This file is part of the KDE project + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_VIDEOWIDGETINTERFACE_H +#define PHONON_VIDEOWIDGETINTERFACE_H + +#include "videowidget.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VIDEO + +namespace Phonon +{ +class VideoWidgetInterface +{ + public: + virtual ~VideoWidgetInterface() {} + + virtual Phonon::VideoWidget::AspectRatio aspectRatio() const = 0; + virtual void setAspectRatio(Phonon::VideoWidget::AspectRatio) = 0; + virtual qreal brightness() const = 0; + virtual void setBrightness(qreal) = 0; + virtual Phonon::VideoWidget::ScaleMode scaleMode() const = 0; + virtual void setScaleMode(Phonon::VideoWidget::ScaleMode) = 0; + virtual qreal contrast() const = 0; + virtual void setContrast(qreal) = 0; + virtual qreal hue() const = 0; + virtual void setHue(qreal) = 0; + virtual qreal saturation() const = 0; + virtual void setSaturation(qreal) = 0; + virtual QWidget *widget() = 0; +//X virtual int overlayCapabilities() const = 0; +//X virtual bool createOverlay(QWidget *widget, int type) = 0; +}; + +class VideoWidgetInterface44 : public VideoWidgetInterface +{ + public: + virtual QImage snapshot() const = 0; +}; +} + +#ifdef PHONON_BACKEND_VERSION_4_4 +namespace Phonon { typedef VideoWidgetInterface44 VideoWidgetInterfaceLatest; } +#else +namespace Phonon { typedef VideoWidgetInterface VideoWidgetInterfaceLatest; } +#endif + +Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface44, "VideoWidgetInterface44.phonon.kde.org") +Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface, "VideoWidgetInterface3.phonon.kde.org") + +#endif //QT_NO_PHONON_VIDEO + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_VIDEOWIDGETINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/volumefadereffect.cpp b/src/3rdparty/phonon/phonon/volumefadereffect.cpp new file mode 100644 index 0000000..15d34ee --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumefadereffect.cpp @@ -0,0 +1,108 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "volumefadereffect.h" +#include "volumefadereffect_p.h" +#include "volumefaderinterface.h" +#include "factory_p.h" + +#include <QtCore/qmath.h> + +#define PHONON_CLASSNAME VolumeFaderEffect +#define PHONON_INTERFACENAME VolumeFaderInterface + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + +namespace Phonon +{ +PHONON_HEIR_IMPL(Effect) + +PHONON_INTERFACE_GETTER(float, volume, d->currentVolume) +PHONON_INTERFACE_SETTER(setVolume, currentVolume, float) +PHONON_INTERFACE_GETTER(Phonon::VolumeFaderEffect::FadeCurve, fadeCurve, d->fadeCurve) +PHONON_INTERFACE_SETTER(setFadeCurve, fadeCurve, Phonon::VolumeFaderEffect::FadeCurve) + +#ifndef PHONON_LOG10OVER20 +#define PHONON_LOG10OVER20 +static const double log10over20 = 0.1151292546497022842; // ln(10) / 20 +#endif // PHONON_LOG10OVER20 + +double VolumeFaderEffect::volumeDecibel() const +{ + return log(volume()) / log10over20; +} + +void VolumeFaderEffect::setVolumeDecibel(double newVolumeDecibel) +{ + setVolume(exp(newVolumeDecibel * log10over20)); +} + + +void VolumeFaderEffect::fadeIn(int fadeTime) +{ + fadeTo(1.0, fadeTime); +} + +void VolumeFaderEffect::fadeOut(int fadeTime) +{ + fadeTo(0.0, fadeTime); +} + +void VolumeFaderEffect::fadeTo(float volume, int fadeTime) +{ + K_D(VolumeFaderEffect); + if (k_ptr->backendObject()) + INTERFACE_CALL(fadeTo(volume, fadeTime)); + else + d->currentVolume = volume; +} + +bool VolumeFaderEffectPrivate::aboutToDeleteBackendObject() +{ + if (m_backendObject) { + currentVolume = pINTERFACE_CALL(volume()); + fadeCurve = pINTERFACE_CALL(fadeCurve()); + } + return true; +} + +void VolumeFaderEffectPrivate::setupBackendObject() +{ + Q_ASSERT(m_backendObject); + + // set up attributes + pINTERFACE_CALL(setVolume(currentVolume)); + pINTERFACE_CALL(setFadeCurve(fadeCurve)); +} +} + + +#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + +QT_END_NAMESPACE + +#include "moc_volumefadereffect.cpp" + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/volumefadereffect.h b/src/3rdparty/phonon/phonon/volumefadereffect.h new file mode 100644 index 0000000..528bffa --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumefadereffect.h @@ -0,0 +1,178 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_VOLUMEFADEREFFECT_H +#define PHONON_VOLUMEFADEREFFECT_H + +#include "phonon_export.h" +#include "effect.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + +namespace Phonon +{ + class VolumeFaderEffectPrivate; + + /** \class VolumeFaderEffect volumefadereffect.h Phonon/VolumeFaderEffect + * Audio effect to gradually fade the audio volume. + * + * This effect differs from gradually changing the output volume in that + * a dedicated effect can change the volume in the smallest possible + * steps while every other volume control will make more or less + * noticeable steps. + * + * \ingroup PhononEffects + * \author Matthias Kretz <kretz@kde.org> + * \see AudioOutput::volume + */ + class PHONON_EXPORT VolumeFaderEffect : public Effect + { + Q_OBJECT + K_DECLARE_PRIVATE(VolumeFaderEffect) + PHONON_HEIR(VolumeFaderEffect) + Q_ENUMS(FadeCurve) + /** + * This is the current volume of the output as voltage factor. + * Setting this property changes the volume immediately. + * + * 1.0 means 100%, 0.5 means 50% voltage/25% power, 0.0 means 0% + * + * \see volumeDecibel + */ + Q_PROPERTY(float volume READ volume WRITE setVolume) + /** + * This is the current volume of the output in decibel. + * Setting this property changes the volume immediately. + * + * 0 dB means no change in volume, -6dB means an attenuation of the + * voltage to 50% and an attenuation of the power to 25%, -inf dB means + * silence. + * + * \see volume + */ + Q_PROPERTY(double volumeDecibel READ volumeDecibel WRITE setVolumeDecibel) + /** + * This property holds the fade curve to be used for the fadeIn(), fadeOut() + * and fadeTo() slots. + * + * Defaults to Fade3Decibel. + * + * \see FadeCurve + */ + Q_PROPERTY(FadeCurve fadeCurve READ fadeCurve WRITE setFadeCurve) + public: + /** + * Determines the curve of the volume change. + */ + enum FadeCurve { + /** + * "Crossfade curve" / "fast" fade out + * + * Often the best fade for a crossfade, as after half of the + * time the volume reached -3dB. This means that half the + * possible power (which is proportional to the square of the + * voltage) is reached. Summed, the maximum power of two audio + * signals fading with a -3dB curve will always be equal. + * + * For fading in or out the -3dB curve is too abrupt in the end. + * + * This is the default fade curve. + */ + Fade3Decibel, + /** + * "Linear" fade out + * + * With a -6dB fade curve after half of the fading time -6dB has + * been reached. -6dB is equal to half of the voltage meaning + * that the voltage multiplier changes linearly from the start + * of the fade to the end. + */ + Fade6Decibel, + /** + * "slow" fade out + * + * After half of the fade time -9dB are reached. So the fade is + * fast in the beginning and slow in the end. This is a good + * fade for ending music. + */ + Fade9Decibel, + /** + * more extreme version of the -9dB fade + */ + Fade12Decibel + }; + + float volume() const; + double volumeDecibel() const; + + FadeCurve fadeCurve() const; + + public Q_SLOTS: + /** + * Tells the Fader to change the volume from the current volume to 100% + * in \p fadeTime milliseconds. + * Short for \c fadeTo(1.0, fadeTime). + * + * \param fadeTime the fade duration in milliseconds + * + * \see fadeTo + * \see volume + */ + void fadeIn(int fadeTime); + + /** + * Tells the Fader to change the volume from the current volume to 0% + * in \p fadeTime milliseconds. + * Short for \c fadeTo(0.0, fadeTime). + * + * \param fadeTime the fade duration in milliseconds + * + * \see fadeTo + */ + void fadeOut(int fadeTime); + + void setVolume(float volume); + void setVolumeDecibel(double volumeDecibel); + + void setFadeCurve(FadeCurve curve); + + /** + * Tells the Fader to change the volume from the current value to + * \p volume in \p fadeTime milliseconds + * + * \see fadeIn + * \see fadeOut + */ + void fadeTo(float volume, int fadeTime); + }; +} //namespace Phonon + +#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // PHONON_VOLUMEFADEREFFECT_H diff --git a/src/3rdparty/phonon/phonon/volumefadereffect_p.h b/src/3rdparty/phonon/phonon/volumefadereffect_p.h new file mode 100644 index 0000000..7937e63 --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumefadereffect_p.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_VOLUMEFADEREFFECT_P_H +#define PHONON_VOLUMEFADEREFFECT_P_H + +#include "volumefadereffect.h" +#include "effect_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + +namespace Phonon +{ +class VolumeFaderEffectPrivate : public EffectPrivate +{ + Q_DECLARE_PUBLIC(VolumeFaderEffect) + PHONON_PRIVATECLASS + protected: + VolumeFaderEffectPrivate() + : currentVolume(1.0) + , fadeCurve(VolumeFaderEffect::Fade3Decibel) + { + // invalid EffectDescription + // ############# parameter functions are incorrect + } + + float currentVolume; + VolumeFaderEffect::FadeCurve fadeCurve; +}; +} + +#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + +QT_END_NAMESPACE + +#endif // PHONON_VOLUMEFADEREFFECT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/volumefaderinterface.h b/src/3rdparty/phonon/phonon/volumefaderinterface.h new file mode 100644 index 0000000..8c6e3a4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumefaderinterface.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_VOLUMEFADERINTERFACE_H +#define PHONON_VOLUMEFADERINTERFACE_H + +#include "volumefadereffect.h" +#include <QtCore/QObject> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + +namespace Phonon +{ +class VolumeFaderInterface +{ + public: + virtual ~VolumeFaderInterface() {} + + virtual float volume() const { return 1.0; } + virtual void setVolume(float) {} + virtual Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const { + return VolumeFaderEffect::Fade3Decibel; + } + virtual void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve) {} + virtual void fadeTo(float, int) {} +}; +} + +Q_DECLARE_INTERFACE(Phonon::VolumeFaderInterface, "VolumeFaderInterface4.phonon.kde.org") + +#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_VOLUMEFADERINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/volumeslider.cpp b/src/3rdparty/phonon/phonon/volumeslider.cpp new file mode 100644 index 0000000..00970c1 --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumeslider.cpp @@ -0,0 +1,262 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "volumeslider.h" +#include "volumeslider_p.h" +#include "audiooutput.h" +#include "phonondefs_p.h" +#include "phononnamespace_p.h" +#include "factory_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMESLIDER + +namespace Phonon +{ +VolumeSlider::VolumeSlider(QWidget *parent) + : QWidget(parent), + k_ptr(new VolumeSliderPrivate(this)) +{ + K_D(VolumeSlider); +#ifndef QT_NO_TOOLTIP + setToolTip(tr("Volume: %1%").arg(100)); +#endif +#ifndef QT_NO_WHATSTHIS + setWhatsThis(tr("Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%").arg(100)); +#endif + + connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_sliderChanged(int))); + connect(&d->muteButton, SIGNAL(clicked()), SLOT(_k_buttonClicked())); + + setFocusProxy(&d->slider); +} + +VolumeSlider::VolumeSlider(AudioOutput *output, QWidget *parent) + : QWidget(parent), + k_ptr(new VolumeSliderPrivate(this)) +{ + K_D(VolumeSlider); +#ifndef QT_NO_TOOLTIP + setToolTip(tr("Volume: %1%").arg(100)); +#endif +#ifndef QT_NO_WHATSTHIS + setWhatsThis(tr("Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%").arg(100)); +#endif + + connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_sliderChanged(int))); + connect(&d->muteButton, SIGNAL(clicked()), SLOT(_k_buttonClicked())); + + if (output) { + d->output = output; + d->slider.setValue(qRound(100 * output->volume())); + d->slider.setEnabled(true); + d->muteButton.setEnabled(true); + connect(output, SIGNAL(volumeChanged(qreal)), SLOT(_k_volumeChanged(qreal))); + connect(output, SIGNAL(mutedChanged(bool)), SLOT(_k_mutedChanged(bool))); + } + + setFocusProxy(&d->slider); +} + +VolumeSlider::~VolumeSlider() +{ + delete k_ptr; +} + +bool VolumeSlider::isMuteVisible() const +{ + return !k_ptr->muteButton.isHidden(); +} + +void VolumeSlider::setMuteVisible(bool visible) +{ + k_ptr->muteButton.setVisible(visible); +} + +QSize VolumeSlider::iconSize() const +{ + return k_ptr->muteButton.iconSize(); +} + +void VolumeSlider::setIconSize(const QSize &iconSize) +{ + pDebug() << Q_FUNC_INFO << iconSize; + k_ptr->muteButton.setIconSize(iconSize); +} + +qreal VolumeSlider::maximumVolume() const +{ + return k_ptr->slider.maximum() * 0.01; +} + +void VolumeSlider::setMaximumVolume(qreal volume) +{ + int max = static_cast<int>(volume * 100); + k_ptr->slider.setMaximum(max); +#ifndef QT_NO_WHATSTHIS + setWhatsThis(tr("Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%") + .arg(max)); +#endif +} + +Qt::Orientation VolumeSlider::orientation() const +{ + return k_ptr->slider.orientation(); +} + +void VolumeSlider::setOrientation(Qt::Orientation o) +{ + K_D(VolumeSlider); + Qt::Alignment align = (o == Qt::Horizontal ? Qt::AlignVCenter : Qt::AlignHCenter); + d->layout.setAlignment(&d->muteButton, align); + d->layout.setAlignment(&d->slider, align); + d->layout.setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom); + d->slider.setOrientation(o); +} + +AudioOutput *VolumeSlider::audioOutput() const +{ + K_D(const VolumeSlider); + return d->output; +} + +void VolumeSlider::setAudioOutput(AudioOutput *output) +{ + K_D(VolumeSlider); + if (d->output) { + disconnect(d->output, 0, this, 0); + } + d->output = output; + if (output) { + d->slider.setValue(qRound(100 * output->volume())); + d->slider.setEnabled(true); + d->muteButton.setEnabled(true); + + d->_k_volumeChanged(output->volume()); + d->_k_mutedChanged(output->isMuted()); + + connect(output, SIGNAL(volumeChanged(qreal)), SLOT(_k_volumeChanged(qreal))); + connect(output, SIGNAL(mutedChanged(bool)), SLOT(_k_mutedChanged(bool))); + } else { + d->slider.setValue(100); + d->slider.setEnabled(false); + d->muteButton.setEnabled(false); + } +} + +void VolumeSliderPrivate::_k_buttonClicked() +{ + if (output) { + output->setMuted(!output->isMuted()); + } else { + slider.setEnabled(false); + muteButton.setEnabled(false); + } +} + +void VolumeSliderPrivate::_k_mutedChanged(bool muted) +{ +#ifndef QT_NO_TOOLTIP + Q_Q(VolumeSlider); +#endif + if (muted) { +#ifndef QT_NO_TOOLTIP + q->setToolTip(VolumeSlider::tr("Muted")); +#endif + muteButton.setIcon(mutedIcon); + } else { +#ifndef QT_NO_TOOLTIP + q->setToolTip(VolumeSlider::tr("Volume: %1%").arg(static_cast<int>(output->volume() * 100.0))); +#endif + muteButton.setIcon(volumeIcon); + } +} + +void VolumeSliderPrivate::_k_sliderChanged(int value) +{ +#ifndef QT_NO_TOOLTIP + Q_Q(VolumeSlider); +#endif + + if (output) { +#ifndef QT_NO_TOOLTIP + if (!output->isMuted()) { + q->setToolTip(VolumeSlider::tr("Volume: %1%").arg(value)); + } +#endif + + ignoreVolumeChange = true; + output->setVolume((static_cast<qreal>(value)) * 0.01); + ignoreVolumeChange = false; + } else { + slider.setEnabled(false); + muteButton.setEnabled(false); + } +} + +void VolumeSliderPrivate::_k_volumeChanged(qreal value) +{ + if (!ignoreVolumeChange) { + slider.setValue(qRound(100 * value)); + } +} + +bool VolumeSlider::hasTracking() const +{ + return k_ptr->slider.hasTracking(); +} + +void VolumeSlider::setTracking(bool tracking) +{ + k_ptr->slider.setTracking(tracking); +} + +int VolumeSlider::pageStep() const +{ + return k_ptr->slider.pageStep(); +} + +void VolumeSlider::setPageStep(int milliseconds) +{ + k_ptr->slider.setPageStep(milliseconds); +} + +int VolumeSlider::singleStep() const +{ + return k_ptr->slider.singleStep(); +} + +void VolumeSlider::setSingleStep(int milliseconds) +{ + k_ptr->slider.setSingleStep(milliseconds); +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE + +#include "moc_volumeslider.cpp" + +// vim: sw=4 et diff --git a/src/3rdparty/phonon/phonon/volumeslider.h b/src/3rdparty/phonon/phonon/volumeslider.h new file mode 100644 index 0000000..f5ef34f --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumeslider.h @@ -0,0 +1,155 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef PHONON_UI_VOLUMESLIDER_H +#define PHONON_UI_VOLUMESLIDER_H + +#include "phonon_export.h" +#include "phonondefs.h" +#include <QtGui/QWidget> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMESLIDER + +namespace Phonon +{ +class AudioOutput; +class VolumeSliderPrivate; + +/** \class VolumeSlider volumeslider.h Phonon/VolumeSlider + * \short Widget providing a slider to control the volume of an AudioOutput. + * + * \ingroup PhononWidgets + * \author Matthias Kretz <kretz@kde.org> + */ +class PHONON_EXPORT VolumeSlider : public QWidget +{ + Q_OBJECT + K_DECLARE_PRIVATE(VolumeSlider) + /** + * This property holds the maximum volume that can be set with this slider. + * + * By default the maximum value is 1.0 (100%). + */ + Q_PROPERTY(qreal maximumVolume READ maximumVolume WRITE setMaximumVolume) + /** + * This property holds the orientation of the slider. + * + * The orientation must be Qt::Vertical (the default) or Qt::Horizontal. + */ + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) + + /** + * This property holds whether slider tracking is enabled. + * + * If tracking is enabled (the default), the volume changes + * while the slider is being dragged. If tracking is + * disabled, the volume changes only when the user + * releases the slider. + */ + Q_PROPERTY(bool tracking READ hasTracking WRITE setTracking) + + /** + * This property holds the page step. + * + * The larger of two natural steps that a slider provides and + * typically corresponds to the user pressing PageUp or PageDown. + * + * Defaults to 5 (5% of the voltage). + */ + Q_PROPERTY(int pageStep READ pageStep WRITE setPageStep) + + /** + * This property holds the single step. + * + * The smaller of two natural steps that a slider provides and + * typically corresponds to the user pressing an arrow key. + * + * Defaults to 1 (1% of the voltage). + */ + Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep) + + /** + * This property holds whether the mute button/icon next to the slider is visible. + * + * By default the mute button/icon is visible. + */ + Q_PROPERTY(bool muteVisible READ isMuteVisible WRITE setMuteVisible) + + /** + * \brief the icon size used for the mute button/icon. + * + * The default size is defined by the GUI style. + */ + Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) + public: + /** + * Constructs a new volume slider with a \p parent. + */ + explicit VolumeSlider(QWidget *parent = 0); + explicit VolumeSlider(AudioOutput *, QWidget *parent = 0); + ~VolumeSlider(); + + bool hasTracking() const; + void setTracking(bool tracking); + int pageStep() const; + void setPageStep(int milliseconds); + int singleStep() const; + void setSingleStep(int milliseconds); + bool isMuteVisible() const; + QSize iconSize() const; + qreal maximumVolume() const; + Qt::Orientation orientation() const; + AudioOutput *audioOutput() const; + + public Q_SLOTS: + void setMaximumVolume(qreal); + void setOrientation(Qt::Orientation); + void setMuteVisible(bool); + void setIconSize(const QSize &size); + + /** + * Sets the audio output object to be controlled by this slider. + */ + void setAudioOutput(Phonon::AudioOutput *); + + protected: + VolumeSliderPrivate *const k_ptr; + + private: + Q_PRIVATE_SLOT(k_ptr, void _k_sliderChanged(int)) + Q_PRIVATE_SLOT(k_ptr, void _k_volumeChanged(qreal)) + Q_PRIVATE_SLOT(k_ptr, void _k_mutedChanged(bool)) + Q_PRIVATE_SLOT(k_ptr, void _k_buttonClicked()) +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 et +#endif // PHONON_UI_VOLUMESLIDER_H diff --git a/src/3rdparty/phonon/phonon/volumeslider_p.h b/src/3rdparty/phonon/phonon/volumeslider_p.h new file mode 100644 index 0000000..623275f --- /dev/null +++ b/src/3rdparty/phonon/phonon/volumeslider_p.h @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef VOLUMESLIDER_P_H +#define VOLUMESLIDER_P_H + +#include "volumeslider.h" +#include "swiftslider_p.h" +#include <QtGui/QBoxLayout> +#include <QtGui/QLabel> +#include <QtGui/QPixmap> +#include <QtGui/QToolButton> +#include "factory_p.h" +#include "audiooutput.h" +#include <QtGui/QIcon> +#include <QtCore/QPointer> +#include "platform_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PHONON_VOLUMESLIDER + +namespace Phonon +{ +class VolumeSliderPrivate +{ + Q_DECLARE_PUBLIC(VolumeSlider) + protected: + VolumeSliderPrivate(VolumeSlider *parent) + : q_ptr(parent), + layout(QBoxLayout::LeftToRight, parent), + slider(Qt::Horizontal, parent), + muteButton(parent), + volumeIcon(Platform::icon(QLatin1String("player-volume"), parent->style())), + mutedIcon(Platform::icon(QLatin1String("player-volume-muted"), parent->style())), + output(0), + ignoreVolumeChange(false) + { + slider.setRange(0, 100); + slider.setPageStep(5); + slider.setSingleStep(1); + + muteButton.setIcon(volumeIcon); + muteButton.setAutoRaise(true); + layout.setMargin(0); + layout.setSpacing(2); + layout.addWidget(&muteButton, 0, Qt::AlignVCenter); + layout.addWidget(&slider, 0, Qt::AlignVCenter); + + slider.setEnabled(false); + muteButton.setEnabled(false); + + if (volumeIcon.isNull()) { + muteButton.setVisible(false); + } + } + + VolumeSlider *q_ptr; + + void _k_sliderChanged(int); + void _k_volumeChanged(qreal); + void _k_mutedChanged(bool); + void _k_buttonClicked(); + + private: + QBoxLayout layout; + SwiftSlider slider; + QToolButton muteButton; + QIcon volumeIcon; + QIcon mutedIcon; + + QPointer<AudioOutput> output; + bool ignoreVolumeChange; +}; +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE + +#endif // VOLUMESLIDER_P_H +// vim: sw=4 sts=4 et tw=100 |