diff --git a/phonon/medianode_p.h b/phonon/medianode_p.h index 68e05cafe7..a83627da4f 100644 --- a/phonon/medianode_p.h +++ b/phonon/medianode_p.h @@ -1,137 +1,139 @@ /* This file is part of the KDE project Copyright (C) 2007 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PHONON_MEDIANODE_P_H #define PHONON_MEDIANODE_P_H #include #include #include #include "path.h" #include "phonon_export.h" 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(this)->qObject(); } virtual QObject *qObject() = 0; protected: MediaNode *q_ptr; + public: QObject *m_backendObject; + protected: QList outputPaths; QList inputPaths; private: QList handlers; Q_DISABLE_COPY(MediaNodePrivate) }; } // namespace Phonon #endif // PHONON_MEDIANODE_P_H diff --git a/phonon/phonondefs_p.h b/phonon/phonondefs_p.h index 8b4379e8c1..82b2c05f16 100644 --- a/phonon/phonondefs_p.h +++ b/phonon/phonondefs_p.h @@ -1,205 +1,277 @@ /* This file is part of the KDE project Copyright (C) 2006-2007 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PHONONDEFS_P_H #define PHONONDEFS_P_H #include +#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)) +namespace Phonon +{ + namespace + { + class NoIface; + + /// undefined result if the condition is neither true nor false + template struct If; + /// If false Else is the Result + template struct If { typedef Else Result; }; + /// If true Then is the Result + template struct If { typedef Then Result; }; + + /// All template arguments are valid + template struct IsValid { enum { Result = true }; }; + /// except NoIface + template<> struct IsValid { enum { Result = false }; }; + + template + struct iface_cast_helper + { + static inline R *help(MediaNodePrivate *d) + { + return qobject_cast(d->m_backendObject); + } + + static inline const R *help(const MediaNodePrivate *d) + { + return qobject_cast(d->m_backendObject); + } + }; + + template + struct iface_cast_helper + { + static inline R *help(const MediaNodePrivate *) + { + return 0; + } + }; + + } // anonymous namespace + + template + struct Iface + { + typedef typename If::Result, T2, typename If::Result, T1, T0>::Result>::Result Type; + static inline Type *cast(MediaNodePrivate *const d) + { + Type *ret; + ret = qobject_cast(d->m_backendObject); + if (ret) return ret; + ret = iface_cast_helper::help(d); + if (ret) return ret; + ret = iface_cast_helper::help(d); + return ret; + } + + static inline const Type *cast(const MediaNodePrivate *const d) + { + const Type *ret; + ret = qobject_cast(d->m_backendObject); + if (ret) return ret; + ret = iface_cast_helper::help(d); + if (ret) return ret; + ret = iface_cast_helper::help(d); + return ret; + } + }; +} // namespace Phonon + #define INTERFACE_CALL(function) \ -qobject_cast(d->m_backendObject)->function +Iface::cast(d)->function #define pINTERFACE_CALL(function) \ -qobject_cast(m_backendObject)->function +Iface::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 qobject_cast(d->m_backendObject)->name(); \ + return Iface::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 qobject_cast(d->m_backendObject)->name(argvar1->k_ptr->backendObject()); \ + return Iface::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()) { \ - qobject_cast(d->m_backendObject)->functionname(x); \ + Iface::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) #endif #endif // PHONONDEFS_P_H