Home | History | Annotate | Download | only in webrtc
      1 /*
      2  * libjingle
      3  * Copyright 2013, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 // This file contains Macros for creating proxies for webrtc MediaStream and
     29 // PeerConnection classes.
     30 
     31 //
     32 // Example usage:
     33 //
     34 // class TestInterface : public talk_base::RefCountInterface {
     35 //  public:
     36 //   std::string FooA() = 0;
     37 //   std::string FooB(bool arg1) const = 0;
     38 //   std::string FooC(bool arg1)= 0;
     39 //  };
     40 //
     41 // Note that return types can not be a const reference.
     42 //
     43 // class Test : public TestInterface {
     44 // ... implementation of the interface.
     45 // };
     46 //
     47 // BEGIN_PROXY_MAP(Test)
     48 //   PROXY_METHOD0(std::string, FooA)
     49 //   PROXY_CONSTMETHOD1(std::string, FooB, arg1)
     50 //   PROXY_METHOD1(std::string, FooC, arg1)
     51 // END_PROXY()
     52 //
     53 // The proxy can be created using TestProxy::Create(Thread*, TestInterface*).
     54 
     55 #ifndef TALK_APP_WEBRTC_PROXY_H_
     56 #define TALK_APP_WEBRTC_PROXY_H_
     57 
     58 #include "talk/base/thread.h"
     59 
     60 namespace webrtc {
     61 
     62 template <typename R>
     63 class ReturnType {
     64  public:
     65   template<typename C, typename M>
     66   void Invoke(C* c, M m) { r_ = (c->*m)(); }
     67   template<typename C, typename M, typename T1>
     68   void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); }
     69   template<typename C, typename M, typename T1, typename T2>
     70   void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); }
     71   template<typename C, typename M, typename T1, typename T2, typename T3>
     72   void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); }
     73 
     74   R value() { return r_; }
     75 
     76  private:
     77   R r_;
     78 };
     79 
     80 template <>
     81 class ReturnType<void> {
     82  public:
     83   template<typename C, typename M>
     84   void Invoke(C* c, M m) { (c->*m)(); }
     85   template<typename C, typename M, typename T1>
     86   void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); }
     87   template<typename C, typename M, typename T1, typename T2>
     88   void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); }
     89   template<typename C, typename M, typename T1, typename T2, typename T3>
     90   void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); }
     91 
     92   void value() {}
     93 };
     94 
     95 template <typename C, typename R>
     96 class MethodCall0 : public talk_base::Message,
     97                     public talk_base::MessageHandler {
     98  public:
     99   typedef R (C::*Method)();
    100   MethodCall0(C* c, Method m) : c_(c), m_(m) {}
    101 
    102   R Marshal(talk_base::Thread* t) {
    103     t->Send(this, 0);
    104     return r_.value();
    105   }
    106 
    107  private:
    108   void OnMessage(talk_base::Message*) {  r_.Invoke(c_, m_);}
    109 
    110   C* c_;
    111   Method m_;
    112   ReturnType<R> r_;
    113 };
    114 
    115 template <typename C, typename R>
    116 class ConstMethodCall0 : public talk_base::Message,
    117                          public talk_base::MessageHandler {
    118  public:
    119   typedef R (C::*Method)() const;
    120   ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
    121 
    122   R Marshal(talk_base::Thread* t) {
    123     t->Send(this, 0);
    124     return r_.value();
    125   }
    126 
    127  private:
    128   void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_); }
    129 
    130   C* c_;
    131   Method m_;
    132   ReturnType<R> r_;
    133 };
    134 
    135 template <typename C, typename R,  typename T1>
    136 class MethodCall1 : public talk_base::Message,
    137                     public talk_base::MessageHandler {
    138  public:
    139   typedef R (C::*Method)(T1 a1);
    140   MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
    141 
    142   R Marshal(talk_base::Thread* t) {
    143     t->Send(this, 0);
    144     return r_.value();
    145   }
    146 
    147  private:
    148   void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_); }
    149 
    150   C* c_;
    151   Method m_;
    152   ReturnType<R> r_;
    153   T1 a1_;
    154 };
    155 
    156 template <typename C, typename R,  typename T1>
    157 class ConstMethodCall1 : public talk_base::Message,
    158                          public talk_base::MessageHandler {
    159  public:
    160   typedef R (C::*Method)(T1 a1) const;
    161   ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
    162 
    163   R Marshal(talk_base::Thread* t) {
    164     t->Send(this, 0);
    165     return r_.value();
    166   }
    167 
    168  private:
    169   void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_); }
    170 
    171   C* c_;
    172   Method m_;
    173   ReturnType<R> r_;
    174   T1 a1_;
    175 };
    176 
    177 template <typename C, typename R, typename T1, typename T2>
    178 class MethodCall2 : public talk_base::Message,
    179                     public talk_base::MessageHandler {
    180  public:
    181   typedef R (C::*Method)(T1 a1, T2 a2);
    182   MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {}
    183 
    184   R Marshal(talk_base::Thread* t) {
    185     t->Send(this, 0);
    186     return r_.value();
    187   }
    188 
    189  private:
    190   void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_, a2_); }
    191 
    192   C* c_;
    193   Method m_;
    194   ReturnType<R> r_;
    195   T1 a1_;
    196   T2 a2_;
    197 };
    198 
    199 template <typename C, typename R, typename T1, typename T2, typename T3>
    200 class MethodCall3 : public talk_base::Message,
    201                     public talk_base::MessageHandler {
    202  public:
    203   typedef R (C::*Method)(T1 a1, T2 a2, T3 a3);
    204   MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3)
    205       : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {}
    206 
    207   R Marshal(talk_base::Thread* t) {
    208     t->Send(this, 0);
    209     return r_.value();
    210   }
    211 
    212  private:
    213   void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); }
    214 
    215   C* c_;
    216   Method m_;
    217   ReturnType<R> r_;
    218   T1 a1_;
    219   T2 a2_;
    220   T3 a3_;
    221 };
    222 
    223 #define BEGIN_PROXY_MAP(c) \
    224   class c##Proxy : public c##Interface {\
    225    protected:\
    226     typedef c##Interface C;\
    227     c##Proxy(talk_base::Thread* thread, C* c)\
    228       : owner_thread_(thread), \
    229         c_(c)  {}\
    230     ~c##Proxy() {\
    231       MethodCall0<c##Proxy, void> call(this, &c##Proxy::Release_s);\
    232       call.Marshal(owner_thread_);\
    233     }\
    234    public:\
    235     static talk_base::scoped_refptr<C> Create(talk_base::Thread* thread, \
    236                                               C* c) {\
    237       return new talk_base::RefCountedObject<c##Proxy>(thread, c);\
    238     }\
    239 
    240 #define PROXY_METHOD0(r, method)\
    241     r method() OVERRIDE {\
    242       MethodCall0<C, r> call(c_.get(), &C::method);\
    243       return call.Marshal(owner_thread_);\
    244     }\
    245 
    246 #define PROXY_CONSTMETHOD0(r, method)\
    247     r method() const OVERRIDE {\
    248       ConstMethodCall0<C, r> call(c_.get(), &C::method);\
    249       return call.Marshal(owner_thread_);\
    250      }\
    251 
    252 #define PROXY_METHOD1(r, method, t1)\
    253     r method(t1 a1) OVERRIDE {\
    254       MethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
    255       return call.Marshal(owner_thread_);\
    256     }\
    257 
    258 #define PROXY_CONSTMETHOD1(r, method, t1)\
    259     r method(t1 a1) const OVERRIDE {\
    260       ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
    261       return call.Marshal(owner_thread_);\
    262     }\
    263 
    264 #define PROXY_METHOD2(r, method, t1, t2)\
    265     r method(t1 a1, t2 a2) OVERRIDE {\
    266       MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2);\
    267       return call.Marshal(owner_thread_);\
    268     }\
    269 
    270 #define PROXY_METHOD3(r, method, t1, t2, t3)\
    271     r method(t1 a1, t2 a2, t3 a3) OVERRIDE {\
    272       MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, a1, a2, a3);\
    273       return call.Marshal(owner_thread_);\
    274     }\
    275 
    276 #define END_PROXY() \
    277    private:\
    278     void Release_s() {\
    279       c_ = NULL;\
    280     }\
    281     mutable talk_base::Thread* owner_thread_;\
    282     talk_base::scoped_refptr<C> c_;\
    283   };\
    284 
    285 }  // namespace webrtc
    286 
    287 #endif  //  TALK_APP_WEBRTC_PROXY_H_
    288