QtGStreamer 0.10.1
|
00001 /* 00002 Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com> 00003 Copyright (C) 2010 Collabora Ltd. 00004 @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk> 00005 00006 This library is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU Lesser General Public License as published 00008 by the Free Software Foundation; either version 2.1 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 #if !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING 00020 00021 # ifndef IN_QGLIB_CONNECT_H 00022 # error "This file must not be included directly" 00023 # endif 00024 00025 # include "value.h" 00026 # include "refpointer.h" 00027 # include <QtCore/QList> 00028 # include <stdexcept> 00029 # include <boost/type_traits.hpp> 00030 00031 00032 namespace QGlib { 00033 namespace Private { 00034 00035 //BEGIN ******** CppClosure prototype ******** 00036 00037 template <typename Function, typename Signature> 00038 struct CppClosure {}; 00039 00040 //END ******** CppClosure prototype ******** 00041 //BEGIN ******** invoker ******** 00042 00043 template <typename Function, typename R> 00044 struct invoker 00045 { 00046 static inline void invoke(const Function & f, Value & result) { ValueImpl<R>::set(result, f()); } 00047 }; 00048 00049 template <typename Function> 00050 struct invoker<Function, void> 00051 { 00052 static inline void invoke(const Function & f, Value &) { f(); } 00053 }; 00054 00055 //END ******** invoker ******** 00056 00057 } //namespace Private 00058 } //namespace QGlib 00059 00060 00061 # if QGLIB_HAVE_CXX0X 00062 00063 namespace QGlib { 00064 namespace Private { 00065 00066 //BEGIN ******** MemberFunction ******** 00067 00068 template <typename T, typename R, typename... Args> 00069 class MemberFunction 00070 { 00071 public: 00072 inline MemberFunction(R (T::*fn)(Args...), T *obj) 00073 : m_function(fn), m_object(obj) {} 00074 00075 inline R operator()(Args&&... args) const 00076 { 00077 return (m_object->*m_function)(std::forward<Args>(args)...); 00078 } 00079 00080 private: 00081 R (T::*m_function)(Args...); 00082 T *m_object; 00083 }; 00084 00085 template <typename T, typename R, typename... Args> 00086 MemberFunction<T, R, Args...> mem_fn(R (T::*fn)(Args...), T *obj) 00087 { 00088 return MemberFunction<T, R, Args...>(fn, obj); 00089 } 00090 00091 //END ******** MemberFunction ******** 00092 //BEGIN ******** BoundArgumentFunction ******** 00093 00094 template <typename ParentFunction, typename R, typename Arg1, typename... Args> 00095 class BoundArgumentFunction 00096 { 00097 public: 00098 inline BoundArgumentFunction(ParentFunction && fn, Arg1 && arg) 00099 : m_function(std::forward<ParentFunction>(fn)), 00100 m_firstArg(std::forward<Arg1>(arg)) {} 00101 00102 inline R operator()(Args&&... args) const 00103 { 00104 return m_function(std::forward<Arg1>(m_firstArg), std::forward<Args>(args)...); 00105 } 00106 00107 private: 00108 ParentFunction && m_function; 00109 Arg1 && m_firstArg; 00110 }; 00111 00112 template <typename F, typename R, typename Arg1, typename... Args> 00113 inline BoundArgumentFunction<F, R, Arg1, Args...> partial_bind(F && f, Arg1 && a1) 00114 { 00115 return BoundArgumentFunction<F, R, Arg1, Args...>(std::forward<F>(f), std::forward<Arg1>(a1)); 00116 } 00117 00118 //END ******** BoundArgumentFunction ******** 00119 //BEGIN ******** unpackAndInvoke ******** 00120 00121 template <typename F, typename R> 00122 inline void unpackAndInvoke(F && function, Value & result, 00123 QList<Value>::const_iterator &&, 00124 QList<Value>::const_iterator &&) 00125 { 00126 invoker<F, R>::invoke(function, result); 00127 } 00128 00129 template <typename F, typename R, typename Arg1, typename... Args> 00130 inline void unpackAndInvoke(F && function, Value & result, 00131 QList<Value>::const_iterator && argsBegin, 00132 QList<Value>::const_iterator && argsEnd) 00133 { 00134 typedef typename boost::remove_const< 00135 typename boost::remove_reference<Arg1>::type 00136 >::type CleanArg1; 00137 typedef BoundArgumentFunction<F, R, Arg1, Args...> F1; 00138 00139 CleanArg1 && boundArg = ValueImpl<CleanArg1>::get(*argsBegin); 00140 F1 && f = partial_bind<F, R, Arg1, Args...>(std::forward<F>(function), std::forward<Arg1>(boundArg)); 00141 00142 unpackAndInvoke< F1, R, Args... >(std::forward<F1>(f), result, 00143 std::forward<QList<Value>::const_iterator>(++argsBegin), 00144 std::forward<QList<Value>::const_iterator>(argsEnd)); 00145 } 00146 00147 //END ******** unpackAndInvoke ******** 00148 //BEGIN ******** CppClosure ******** 00149 00150 template <typename F, typename R, typename... Args> 00151 struct CppClosure<F, R (Args...)> 00152 { 00153 class ClosureData : public ClosureDataBase 00154 { 00155 public: 00156 inline ClosureData(const F & func, bool passSender) 00157 : ClosureDataBase(passSender), m_function(func) {} 00158 00159 virtual void marshaller(Value & result, const QList<Value> & params) 00160 { 00161 if (static_cast<unsigned int>(params.size()) < sizeof...(Args)) { 00162 throw std::logic_error("The signal provides less arguments than what the closure expects"); 00163 } 00164 00165 unpackAndInvoke<F, R, Args...>(std::forward<F>(m_function), result, 00166 params.constBegin(), params.constEnd()); 00167 } 00168 00169 private: 00170 F m_function; 00171 }; 00172 00173 static inline ClosureDataBase *create(const F & function, bool passSender) 00174 { 00175 return new ClosureData(function, passSender); 00176 } 00177 }; 00178 00179 //END ******** CppClosure ******** 00180 00181 } //namespace Private 00182 00183 //BEGIN ******** QGlib::connect ******** 00184 00185 template <typename T, typename R, typename... Args> 00186 bool connect(void *instance, const char *detailedSignal, 00187 T *receiver, R (T::*slot)(Args...), ConnectFlags flags = 0) 00188 { 00189 typedef Private::MemberFunction<T, R, Args...> F; 00190 00191 F && f = Private::mem_fn(slot, receiver); 00192 Private::ClosureDataBase* && closure 00193 = Private::CppClosure<F, R (Args...)>::create(f, flags & PassSender); 00194 00195 return Private::connect(instance, detailedSignal, Quark(), 00196 receiver, Private::GetDestroyNotifier<T>(), 00197 Private::hashMfp(slot), closure, flags); 00198 } 00199 00200 //END ******** QGlib::connect ******** 00201 00202 } //namespace QGlib 00203 00204 # else //QGLIB_HAVE_CXX0X 00205 00206 # include <boost/function.hpp> 00207 # include <boost/preprocessor.hpp> 00208 # include <boost/bind.hpp> 00209 00210 // include the second part of this file as many times as QGLIB_CONNECT_MAX_ARGS specifies 00211 # define BOOST_PP_ITERATION_PARAMS_1 (3,(0, QGLIB_CONNECT_MAX_ARGS, "QGlib/connectimpl.h")) 00212 # include BOOST_PP_ITERATE() 00213 00214 # undef BOOST_PP_ITERATION_PARAMS_1 00215 # undef QGLIB_CONNECT_MAX_ARGS 00216 00217 # endif //QGLIB_HAVE_CXX0X 00218 00219 00220 #else // !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING 00221 00222 /* 00223 This part is included from BOOST_PP_ITERATE(). It defines a CppClosureN class 00224 (where N is the number of template arguments it takes) and a specialization for class 00225 CppClosure, so that the CppClosure<R (Args...), F> syntax is supported. This part is 00226 included multiple times (QGLIB_CONNECT_MAX_ARGS defines how many), and each time 00227 it defines those classes with different number of arguments. 00228 The concept is based on the implementation of boost::function. 00229 */ 00230 00231 # define QGLIB_CONNECT_IMPL_NUM_ARGS \ 00232 BOOST_PP_ITERATION() 00233 00234 # define QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS \ 00235 BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_CONNECT_IMPL_NUM_ARGS, typename A) 00236 00237 # define QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_ARGS \ 00238 BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_CONNECT_IMPL_NUM_ARGS, A) 00239 00240 # define QGLIB_CONNECT_IMPL_TEMPLATE_ARGS \ 00241 BOOST_PP_ENUM_PARAMS(QGLIB_CONNECT_IMPL_NUM_ARGS, A) 00242 00243 namespace QGlib { 00244 namespace Private { 00245 00246 //BEGIN ******** boostpp CppClosure ******** 00247 00248 # define QGLIB_CONNECT_IMPL_CPPCLOSUREN \ 00249 BOOST_PP_CAT(CppClosure, QGLIB_CONNECT_IMPL_NUM_ARGS) 00250 00251 # define QGLIB_CONNECT_IMPL_UNPACK_ARGS_STEP(z, n, list) \ 00252 ,ValueImpl< \ 00253 typename boost::remove_const< \ 00254 typename boost::remove_reference<A ##n>::type \ 00255 >::type \ 00256 >::get(list.at(n)) 00257 00258 # define QGLIB_CONNECT_IMPL_UNPACK_ARGS(list) \ 00259 BOOST_PP_REPEAT(QGLIB_CONNECT_IMPL_NUM_ARGS, QGLIB_CONNECT_IMPL_UNPACK_ARGS_STEP, list) 00260 00261 template <typename F, typename R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS> 00262 struct QGLIB_CONNECT_IMPL_CPPCLOSUREN 00263 { 00264 class ClosureData : public ClosureDataBase 00265 { 00266 public: 00267 inline ClosureData(const F & func, bool passSender) 00268 : ClosureDataBase(passSender), m_function(func) {} 00269 00270 virtual void marshaller(Value & result, const QList<Value> & params) 00271 { 00272 if (params.size() < QGLIB_CONNECT_IMPL_NUM_ARGS) { 00273 throw std::logic_error("The signal provides less arguments than what the closure expects"); 00274 } 00275 00276 # if QGLIB_CONNECT_IMPL_NUM_ARGS > 0 00277 boost::function<R ()> callback = boost::bind<R>(m_function 00278 QGLIB_CONNECT_IMPL_UNPACK_ARGS(params)); 00279 invoker< boost::function<R ()>, R >::invoke(callback, result); 00280 # else 00281 invoker< F, R >::invoke(m_function, result); 00282 # endif 00283 } 00284 00285 private: 00286 F m_function; 00287 }; 00288 00289 static ClosureDataBase *create(const F & function, bool passSender) 00290 { 00291 return new ClosureData(function, passSender); 00292 } 00293 }; 00294 00295 //partial specialization of struct CppClosure to support the CppClosure<F, R (Args...)> syntax 00296 template <typename F, typename R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS> 00297 struct CppClosure<F, R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)> 00298 : public QGLIB_CONNECT_IMPL_CPPCLOSUREN< F, R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_ARGS > 00299 { 00300 }; 00301 00302 # undef QGLIB_CONNECT_IMPL_UNPACK_ARGS 00303 # undef QGLIB_CONNECT_IMPL_UNPACK_ARGS_STEP 00304 # undef QGLIB_CONNECT_IMPL_CPPCLOSUREN 00305 00306 //END ******** boostpp CppClosure ******** 00307 00308 } //namespace Private 00309 00310 //BEGIN ******** bostpp QGlib::connect ******** 00311 00312 # define QGLIB_CONNECT_IMPL_BIND_ARGS \ 00313 BOOST_PP_COMMA_IF(QGLIB_CONNECT_IMPL_NUM_ARGS) \ 00314 BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(QGLIB_CONNECT_IMPL_NUM_ARGS), _) 00315 00316 template <typename T, typename R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS> 00317 bool connect(void *instance, const char *detailedSignal, 00318 T *receiver, R (T::*slot)(QGLIB_CONNECT_IMPL_TEMPLATE_ARGS), ConnectFlags flags = 0) 00319 { 00320 boost::function<R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)> f 00321 = boost::bind(slot, receiver QGLIB_CONNECT_IMPL_BIND_ARGS); 00322 00323 Private::ClosureDataBase *closure = Private::CppClosure< 00324 boost::function<R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)>, 00325 R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS) 00326 >::create(f, flags & PassSender); 00327 00328 return Private::connect(instance, detailedSignal, Quark(), 00329 receiver, Private::GetDestroyNotifier<T>(), 00330 Private::hashMfp(slot), closure, flags); 00331 } 00332 00333 # undef QGLIB_CONNECT_IMPL_BIND_ARGS 00334 00335 //END ******** bostpp QGlib::connect ******** 00336 00337 } //namespace QGlib 00338 00339 # undef QGLIB_CONNECT_IMPL_TEMPLATE_ARGS 00340 # undef QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_ARGS 00341 # undef QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS 00342 # undef QGLIB_CONNECT_IMPL_NUM_ARGS 00343 00344 #endif // !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING