add more spacing
[personal-kdebase.git] / runtime / phonon / kcm / phonondefs_p.h
blob4eeb91bef2f96a5b95c526515d95012bb204dd5b
1 /* This file is part of the KDE project
2 Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
20 #ifndef PHONONDEFS_P_H
21 #define PHONONDEFS_P_H
23 #include <QtCore/QMetaType>
24 #include "medianode_p.h"
26 #define K_D(Class) Class##Private *const d = k_func()
28 #define PHONON_CONCAT_HELPER_INTERNAL(x, y) x ## y
29 #define PHONON_CONCAT_HELPER(x, y) PHONON_CONCAT_HELPER_INTERNAL(x, y)
31 #define PHONON_PRIVATECLASS \
32 protected: \
33 virtual bool aboutToDeleteBackendObject(); \
34 virtual void createBackendObject(); \
35 /**
36 * \internal
37 * After construction of the Iface object this method is called
38 * throughout the complete class hierarchy in order to set up the
39 * properties that were already set on the public interface.
41 * An example implementation could look like this:
42 * \code
43 * ParentClassPrivate::setupBackendObject();
44 * m_iface->setPropertyA(d->propertyA);
45 * m_iface->setPropertyB(d->propertyB);
46 * \endcode
47 */ \
48 void setupBackendObject();
50 #define PHONON_PRIVATEABSTRACTCLASS \
51 protected: \
52 virtual bool aboutToDeleteBackendObject(); \
53 /**
54 * \internal
55 * After construction of the Iface object this method is called
56 * throughout the complete class hierarchy in order to set up the
57 * properties that were already set on the public interface.
59 * An example implementation could look like this:
60 * \code
61 * ParentClassPrivate::setupBackendObject();
62 * m_iface->setPropertyA(d->propertyA);
63 * m_iface->setPropertyB(d->propertyB);
64 * \endcode
65 */ \
66 void setupBackendObject();
68 #define PHONON_ABSTRACTBASE_IMPL \
69 PHONON_CLASSNAME::PHONON_CLASSNAME(PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) &dd, QObject *parent) \
70 : QObject(parent), \
71 MediaNode(dd) \
72 { \
75 #define PHONON_OBJECT_IMPL \
76 PHONON_CLASSNAME::PHONON_CLASSNAME(QObject *parent) \
77 : QObject(parent), \
78 MediaNode(*new PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)()) \
79 { \
80 } \
81 void PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)::createBackendObject() \
82 { \
83 if (m_backendObject) \
84 return; \
85 Q_Q(PHONON_CLASSNAME); \
86 m_backendObject = Factory::PHONON_CONCAT_HELPER(create, PHONON_CLASSNAME)(q); \
87 if (m_backendObject) { \
88 setupBackendObject(); \
89 } \
92 #define PHONON_HEIR_IMPL(parentclass) \
93 PHONON_CLASSNAME::PHONON_CLASSNAME(QObject *parent) \
94 : parentclass(*new PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private), parent) \
95 { \
96 } \
97 void PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)::createBackendObject() \
98 { \
99 if (m_backendObject) \
100 return; \
101 Q_Q(PHONON_CLASSNAME); \
102 m_backendObject = Factory::PHONON_CONCAT_HELPER(create, PHONON_CLASSNAME)(q); \
103 if (m_backendObject) { \
104 setupBackendObject(); \
108 #define BACKEND_GET(returnType, returnVar, methodName) \
109 QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar))
110 #define BACKEND_GET1(returnType, returnVar, methodName, varType1, var1) \
111 QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1))
112 #define BACKEND_GET2(returnType, returnVar, methodName, varType1, var1, varType2, var2) \
113 QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1), Q_ARG(varType2, var2))
114 #define BACKEND_CALL(methodName) \
115 QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection)
116 #define BACKEND_CALL1(methodName, varType1, var1) \
117 QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1))
118 #define BACKEND_CALL2(methodName, varType1, var1, varType2, var2) \
119 QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1), Q_ARG(varType2, var2))
121 #define pBACKEND_GET(returnType, returnVar, methodName) \
122 QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar))
123 #define pBACKEND_GET1(returnType, returnVar, methodName, varType1, var1) \
124 QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1))
125 #define pBACKEND_GET2(returnType, returnVar, methodName, varType1, var1, varType2, var2) \
126 QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1), Q_ARG(varType2, var2))
127 #define pBACKEND_CALL(methodName) \
128 QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection)
129 #define pBACKEND_CALL1(methodName, varType1, var1) \
130 QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1))
131 #define pBACKEND_CALL2(methodName, varType1, var1, varType2, var2) \
132 QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1), Q_ARG(varType2, var2))
134 QT_BEGIN_NAMESPACE
136 namespace Phonon
138 namespace
140 class NoIface;
142 /// All template arguments are valid
143 template<typename T> struct IsValid { enum { Result = true }; };
144 /// except NoIface
145 template<> struct IsValid<NoIface> { enum { Result = false }; };
147 template<class T> inline T my_cast(QObject *o) { return qobject_cast<T>(o); }
148 template<class T> inline T my_cast(const QObject *o) { return qobject_cast<T>(o); }
150 template<> inline NoIface *my_cast<NoIface *>(QObject *) { return 0; }
151 template<> inline NoIface *my_cast<NoIface *>(const QObject *) { return 0; }
152 } // anonymous namespace
155 * \internal
157 * \brief Helper class to cast the backend object to the correct version of the interface.
159 * Additions to the backend interfaces cannot be done by adding virtual methods as that would
160 * break the binary interface. So the old class is renamed and a new class with the old name
161 * inheriting the old class is added, containing all the new virtual methods.
162 * Example:
163 * \code
164 class FooInterface
166 public:
167 virtual ~FooInterface() {}
168 virtual oldMethod() = 0;
170 Q_DECLARE_INTERFACE(FooInterface, "FooInterface0.phonon.kde.org")
171 * \endcode
172 * becomes
173 * \code
174 class FooInterface0
176 public:
177 virtual ~FooInterface0() {}
178 virtual oldMethod() = 0;
180 class FooInterface : public FooInterface0
182 public:
183 virtual newMethod() = 0;
185 Q_DECLARE_INTERFACE(FooInterface0, "FooInterface0.phonon.kde.org")
186 Q_DECLARE_INTERFACE(FooInterface, "FooInterface1.phonon.kde.org")
187 * \endcode
189 * With this, backends compiled against the old header can be qobject_casted to FooInterface0,
190 * but not to FooInterface. On the other hand backends compiled against the new header (they first
191 * need to implement newMethod) can only be qobject_casted to FooInterface but not to
192 * FooInterface0. (The qobject_cast relies on the string in Q_DECLARE_INTERFACE and not the
193 * class name which is why it behaves that way.)
195 * Now, in order to call oldMethod, the code needs to try to cast to both FooInterface and
196 * FooInterface0 (new backends will work with the former, old backends with the latter) and then
197 * if one of them in non-zero call oldMethod on it.
199 * To call newMethod only a cast to FooInterface needs to be done.
201 * The Iface class does all this for you for up to three (for now) interface revisions. Just
202 * create an object like this:
203 * \code
204 Iface<FooInterface0, FooInterface> iface0(d);
205 if (iface0) {
206 iface0->oldMethod();
208 Iface<FooInterface> iface(d);
209 if (iface) {
210 iface->newMethod();
212 * \endcode
214 * This becomes a bit more convenient if you add macros like this:
215 * \code
216 #define IFACES1 FooInterface
217 #define IFACES0 FooInterface0, IFACES1
218 * \endcode
219 * which you can use like this:
220 * \code
221 Iface<IFACES0> iface0(d);
222 if (iface0) {
223 iface0->oldMethod();
225 Iface<IFACES1> iface(d);
226 if (iface) {
227 iface->newMethod();
229 * \endcode
230 * With the next revision you can then change the macros to
231 * \code
232 #define IFACES2 FooInterface
233 #define IFACES1 FooInterface1, IFACES2
234 #define IFACES0 FooInterface0, IFACES1
235 * \endcode
237 * \author Matthias Kretz <kretz@kde.org>
239 template<class T0, class T1 = NoIface, class T2 = NoIface>
240 class Iface
242 public:
243 static inline T0 *cast(MediaNodePrivate *const d)
245 if (IsValid<T1>::Result) {
246 T0 *ret;
247 if (IsValid<T2>::Result) {
248 ret = reinterpret_cast<T0 *>(my_cast<T2 *>(d->m_backendObject));
249 if (ret) return ret;
251 ret = reinterpret_cast<T0 *>(my_cast<T1 *>(d->m_backendObject));
252 if (ret) return ret;
254 return qobject_cast<T0 *>(d->m_backendObject);
257 static inline const T0 *cast(const MediaNodePrivate *const d)
259 if (IsValid<T1>::Result) {
260 const T0 *ret;
261 if (IsValid<T2>::Result) {
262 ret = reinterpret_cast<const T0 *>(my_cast<T2 *>(d->m_backendObject));
263 if (ret) return ret;
265 ret = reinterpret_cast<const T0 *>(my_cast<T1 *>(d->m_backendObject));
266 if (ret) return ret;
268 return qobject_cast<T0 *>(d->m_backendObject);
271 inline Iface(MediaNodePrivate *const d) : iface(cast(d)) {}
272 inline operator T0 *() { return iface; }
273 inline operator const T0 *() const { return iface; }
274 inline T0 *operator->() { Q_ASSERT(iface); return iface; }
275 inline const T0 *operator->() const { Q_ASSERT(iface); return iface; }
276 private:
277 T0 *const iface;
280 template<class T0, class T1 = NoIface, class T2 = NoIface>
281 class ConstIface
283 public:
284 inline ConstIface(const MediaNodePrivate *const d) : iface(Iface<T0, T1, T2>::cast(d)) {}
285 inline operator const T0 *() const { return iface; }
286 inline const T0 *operator->() const { Q_ASSERT(iface); return iface; }
287 private:
288 const T0 *const iface;
290 } // namespace Phonon
292 QT_END_NAMESPACE
294 #define INTERFACE_CALL(function) \
295 Iface<PHONON_INTERFACENAME >::cast(d)->function
297 #define pINTERFACE_CALL(function) \
298 Iface<PHONON_INTERFACENAME >::cast(this)->function
300 #define PHONON_GETTER(rettype, name, retdefault) \
301 rettype PHONON_CLASSNAME::name() const \
303 const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
304 if (!d->m_backendObject) \
305 return retdefault; \
306 rettype ret; \
307 BACKEND_GET(rettype, ret, #name); \
308 return ret; \
311 #define PHONON_INTERFACE_GETTER(rettype, name, retdefault) \
312 rettype PHONON_CLASSNAME::name() const \
314 const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
315 if (!d->m_backendObject) \
316 return retdefault; \
317 return Iface<PHONON_INTERFACENAME >::cast(d)->name(); \
320 #define PHONON_GETTER1(rettype, name, retdefault, argtype1, argvar1) \
321 rettype PHONON_CLASSNAME::name(argtype1 argvar1) const \
323 const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
324 if (!d->m_backendObject) \
325 return retdefault; \
326 rettype ret; \
327 BACKEND_GET1(rettype, ret, #name, const QObject *, argvar1->k_ptr->backendObject()); \
328 return ret; \
331 #define PHONON_INTERFACE_GETTER1(rettype, name, retdefault, argtype1, argvar1) \
332 rettype PHONON_CLASSNAME::name(argtype1 argvar1) const \
334 const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
335 if (!d->m_backendObject) \
336 return retdefault; \
337 return Iface<PHONON_INTERFACENAME >::cast(d)->name(argvar1->k_ptr->backendObject()); \
340 #define PHONON_SETTER(functionname, privatevar, argtype1) \
341 void PHONON_CLASSNAME::functionname(argtype1 x) \
343 PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
344 d->privatevar = x; \
345 if (k_ptr->backendObject()) { \
346 BACKEND_CALL1(#functionname, argtype1, x); \
350 #define PHONON_INTERFACE_SETTER(functionname, privatevar, argtype1) \
351 void PHONON_CLASSNAME::functionname(argtype1 x) \
353 PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
354 d->privatevar = x; \
355 if (k_ptr->backendObject()) { \
356 Iface<PHONON_INTERFACENAME >::cast(d)->functionname(x); \
360 #ifndef METATYPE_QLIST_INT_DEFINED
361 #define METATYPE_QLIST_INT_DEFINED
362 // Want this exactly once, see phonondefs_p.h kcm/outputdevicechoice.cpp
363 Q_DECLARE_METATYPE(QList<int>)
364 #endif
366 #endif // PHONONDEFS_P_H