diff --git a/wrappers/cpp/class_header.mustache b/wrappers/cpp/class_header.mustache index 1ed4112ff..4aca63452 100644 --- a/wrappers/cpp/class_header.mustache +++ b/wrappers/cpp/class_header.mustache @@ -74,14 +74,15 @@ namespace linphone { {{/ismonolistenable}} {{#ismultilistenable}} - LINPHONECXX_PUBLIC void addListener(std::shared_ptr<{{{listenerClassName}}}> &listener); - LINPHONECXX_PUBLIC void removeListener(std::shared_ptr<{{{listenerClassName}}}> &listener); + LINPHONECXX_PUBLIC virtual ~{{{className}}}(); + LINPHONECXX_PUBLIC void addListener(const std::shared_ptr<{{{listenerClassName}}}> &listener); + LINPHONECXX_PUBLIC void removeListener(const std::shared_ptr<{{{listenerClassName}}}> &listener); {{/ismultilistenable}} public: {{#isfactory}} - LINPHONECXX_PUBLIC std::shared_ptr createCore(const std::shared_ptr & cbs, const std::string & configPath, const std::string & factoryConfigPath) const; - LINPHONECXX_PUBLIC std::shared_ptr createCoreWithConfig(const std::shared_ptr & cbs, const std::shared_ptr & config) const; + LINPHONECXX_PUBLIC std::shared_ptr createCore(const std::shared_ptr &listener, const std::string & configPath, const std::string & factoryConfigPath) const; + LINPHONECXX_PUBLIC std::shared_ptr createCoreWithConfig(const std::shared_ptr &listener, const std::shared_ptr & config) const; {{/isfactory}} {{#isVcard}} LINPHONECXX_PUBLIC std::shared_ptr &getVcard(); @@ -98,7 +99,7 @@ namespace linphone { {{#ismultilistenable}} private: - static {{{cListenerName}}} *createCallbacks(const std::shared_ptr<{{{listenerClassName}}}> &listener); + static {{{cListenerName}}} *createCallbacks(void *userData); {{/ismultilistenable}} {{#islistenable}} @@ -107,6 +108,12 @@ namespace linphone { {{decl}} {{/wrapperCbs}} {{/islistenable}} + + {{#ismultilistenable}} + private: + {{{cListenerName}}} *mCallbacks; + {{/ismultilistenable}} + }; {{/_class}} diff --git a/wrappers/cpp/class_impl.mustache b/wrappers/cpp/class_impl.mustache index 006bfd376..8e7d9ba13 100644 --- a/wrappers/cpp/class_impl.mustache +++ b/wrappers/cpp/class_impl.mustache @@ -23,7 +23,12 @@ using namespace {{{namespace}}}; {{#_class}} {{#isNotListener}} -{{{namespace}}}::{{{className}}}::{{{className}}}(::belle_sip_object_t *ptr, bool takeRef): {{{parentClassName}}}(ptr, takeRef) {} +{{{namespace}}}::{{{className}}}::{{{className}}}(::belle_sip_object_t *ptr, bool takeRef): {{{parentClassName}}}(ptr, takeRef) { + {{#ismultilistenable}} + mCallbacks = createCallbacks(&getListeners()); + {{{callbacksAdder}}}(({{{cClassName}}} *)mPrivPtr, mCallbacks); + {{/ismultilistenable}} +} {{/isNotListener}} {{#ismonolistenable}} @@ -43,58 +48,70 @@ void {{{namespace}}}::{{{className}}}::setListener(const std::shared_ptr<{{{list {{/ismonolistenable}} {{#ismultilistenable}} -{{{cListenerName}}} *{{{className}}}::createCallbacks(const std::shared_ptr<{{{listenerClassName}}}> &listener) { +{{{className}}}::~{{{className}}}() { + {{{callbacksRemover}}}(({{{cClassName}}} *)mPrivPtr, mCallbacks); + belle_sip_object_unref(mCallbacks); +} + +void {{{className}}}::addListener(const std::shared_ptr<{{{listenerClassName}}}> &listener) { + MultiListenableObject::addListener(std::static_pointer_cast(listener)); +} + +void {{{className}}}::removeListener(const std::shared_ptr<{{{listenerClassName}}}> &listener) { + MultiListenableObject::removeListener(std::static_pointer_cast(listener)); +} + +{{{cListenerName}}} *{{{className}}}::createCallbacks(void *userData) { {{{cListenerName}}} *cbs = {{{listenerCreator}}}(linphone_factory_get()); - {{{userDataSetter}}}(cbs, listener.get()); {{#wrapperCbs}} {{{callbackSetter}}}(cbs, {{{cbName}}}); {{/wrapperCbs}} + {{{userDataSetter}}}(cbs, userData); return cbs; } - -void {{{className}}}::addListener(std::shared_ptr<{{{listenerClassName}}}> &listener) { - MultiListenableObject::addListener(std::static_pointer_cast(listener)); - {{{cListenerName}}} *cbs = createCallbacks(listener); - {{{callbacksAdder}}}(({{{cClassName}}} *)mPrivPtr, cbs); - listener->setCallbacks((::belle_sip_object_t *)cbs); - belle_sip_object_unref(cbs); -} - -void {{{className}}}::removeListener(std::shared_ptr<{{{listenerClassName}}}> &listener) { - ::belle_sip_object_t *cbs = belle_sip_object_ref(listener->getCallbacks()); - {{{callbacksRemover}}}(({{{cClassName}}} *)mPrivPtr, ({{{cListenerName}}} *)cbs); - listener->setCallbacks(NULL); - belle_sip_object_unref(cbs); - - MultiListenableObject::removeListener(listener); -} {{/ismultilistenable}} {{#isfactory}} -std::shared_ptr Factory::createCore(const std::shared_ptr & cbs, const std::string & configPath, const std::string & factoryConfigPath) const { - ::LinphoneFactory *factory = linphone_factory_get(); - ::LinphoneCoreCbs *c_cbs = cbs != nullptr ? Core::createCallbacks(cbs) : NULL; - ::LinphoneCore *core_ptr = linphone_factory_create_core(factory, c_cbs, cppStringToC(configPath), cppStringToC(factoryConfigPath)); - std::shared_ptr core = cPtrToSharedPtr((belle_sip_object_t *)core_ptr, false); - if (core != nullptr && cbs != nullptr) { - std::static_pointer_cast(core)->addListener(cbs); - cbs->setCallbacks((belle_sip_object_t *)c_cbs); +std::shared_ptr Factory::createCore(const std::shared_ptr & listener, const std::string & configPath, const std::string & factoryConfigPath) const { + ::LinphoneCoreCbs *cbs = NULL; + if (listener != nullptr) { + std::list > listeners; + listeners.push_back(std::static_pointer_cast(listener)); + cbs = Core::createCallbacks(&listeners); } - if (c_cbs) linphone_core_cbs_unref(c_cbs); - return core; + + ::LinphoneFactory *factory = linphone_factory_get(); + ::LinphoneCore *core_ptr = linphone_factory_create_core(factory, cbs, cppStringToC(configPath), cppStringToC(factoryConfigPath)); + + if (cbs != NULL) { + linphone_core_remove_callbacks(core_ptr, cbs); + linphone_core_cbs_unref(cbs); + } + + std::shared_ptr cppCore = cPtrToSharedPtr((::belle_sip_object_t *)core_ptr, false); + if (listener != nullptr) cppCore->addListener(listener); + return cppCore; } -std::shared_ptr Factory::createCoreWithConfig(const std::shared_ptr & cbs, const std::shared_ptr & config) const { - ::LinphoneFactory *factory = linphone_factory_get(); - ::LinphoneCoreCbs *c_cbs = cbs != nullptr ? Core::createCallbacks(cbs) : NULL; - ::LinphoneCore *core_ptr = linphone_factory_create_core_with_config(factory, c_cbs, (::LinphoneConfig *)sharedPtrToCPtr(config)); - std::shared_ptr core = cPtrToSharedPtr((belle_sip_object_t *)core_ptr, false); - if (core != nullptr && cbs != nullptr) { - std::static_pointer_cast(core)->addListener(cbs); - cbs->setCallbacks((belle_sip_object_t *)c_cbs); +std::shared_ptr Factory::createCoreWithConfig(const std::shared_ptr & listener, const std::shared_ptr & config) const { + ::LinphoneCoreCbs *cbs = NULL; + if (listener != nullptr) { + std::list > listeners; + listeners.push_back(std::static_pointer_cast(listener)); + cbs = Core::createCallbacks(&listeners); } - if (c_cbs) linphone_core_cbs_unref(c_cbs); - return core; + + ::LinphoneFactory *factory = linphone_factory_get(); + ::LinphoneCore *core_ptr = linphone_factory_create_core_with_config(factory, cbs, (::LinphoneConfig *)sharedPtrToCPtr(config)); + + if (cbs != NULL) { + linphone_core_remove_callbacks(core_ptr, cbs); + linphone_core_cbs_unref(cbs); + } + + std::shared_ptr cppCore = cPtrToSharedPtr((::belle_sip_object_t *)core_ptr, false); + if (listener != nullptr) cppCore->addListener(listener); + return cppCore; } {{/isfactory}} @@ -118,12 +135,19 @@ std::shared_ptr &Vcard::getVcard() { {{#wrapperCbs}} {{{returnType}}} {{{className}}}::{{{cbName}}}({{{declArgs}}}) { - {{#ismonolistenable}}std::shared_ptr<{{{cppListenerName}}}> listener = std::static_pointer_cast<{{{cppListenerName}}},Listener>(getListenerFromObject((::belle_sip_object_t *){{{firstArgName}}}));{{/ismonolistenable}} - {{#ismultilistenable}} - LinphoneCoreCbs *cbs = linphone_core_get_current_callbacks(lc); - CoreListener *listener = (CoreListener *)linphone_core_cbs_get_user_data(cbs); - {{/ismultilistenable}} + {{#ismonolistenable}} + std::shared_ptr<{{{cppListenerName}}}> listener = std::static_pointer_cast<{{{cppListenerName}}},Listener>(getListenerFromObject((::belle_sip_object_t *){{{firstArgName}}})); {{#hasReturnValue}}return {{/hasReturnValue}}{{{cppMethodCallingLine}}}; + {{/ismonolistenable}} + + {{#ismultilistenable}} + {{{cListenerName}}} *cbs = {{{currentCallbacksGetter}}}({{{firstArgName}}}); + std::list > &listeners = *(std::list > *){{{userDataGetter}}}(cbs); + for(auto it=listeners.begin(); it!=listeners.end(); it++) { + std::shared_ptr<{{{cppListenerName}}}> listener = std::static_pointer_cast<{{{cppListenerName}}},Listener>(*it); + {{{cppMethodCallingLine}}}; + } + {{/ismultilistenable}} } {{/wrapperCbs}} diff --git a/wrappers/cpp/genwrapper.py b/wrappers/cpp/genwrapper.py index 51abfcefe..70c186759 100755 --- a/wrappers/cpp/genwrapper.py +++ b/wrappers/cpp/genwrapper.py @@ -88,12 +88,12 @@ class CppTranslator(object): if islistenable: classDict['listenerClassName'] = CppTranslator.translate_class_name(_class.listenerInterface.name) classDict['cListenerName'] = _class.listenerInterface.name.to_c() + classDict['cppListenerName'] = CppTranslator.translate_class_name(_class.listenerInterface.name) for method in _class.listenerInterface.methods: classDict['wrapperCbs'].append(CppTranslator._generate_wrapper_callback(self, _class, method)) if ismonolistenable: classDict['cCbsGetter'] = _class.name.to_snake_case(fullName=True) + '_get_callbacks' - classDict['cppListenerName'] = CppTranslator.translate_class_name(_class.listenerInterface.name) classDict['parentClassName'] = 'ListenableObject' elif ismultilistenable: classDict['parentClassName'] = 'MultiListenableObject' @@ -101,6 +101,8 @@ class CppTranslator(object): classDict['callbacksAdder'] = _class.name.to_snake_case(fullName=True)+ '_add_callbacks' classDict['callbacksRemover'] = _class.name.to_snake_case(fullName=True)+ '_remove_callbacks' classDict['userDataSetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_set_user_data' + classDict['userDataGetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_get_user_data' + classDict['currentCallbacksGetter'] = _class.name.to_snake_case(fullName=True) + '_get_current_callbacks' for property in _class.properties: try: diff --git a/wrappers/cpp/object.cc b/wrappers/cpp/object.cc index 7afb183cc..a4d590e78 100644 --- a/wrappers/cpp/object.cc +++ b/wrappers/cpp/object.cc @@ -170,15 +170,15 @@ std::string MultiListenableObject::sListenerListName = "cpp_listeners"; MultiListenableObject::MultiListenableObject(::belle_sip_object_t *ptr, bool takeRef): Object(ptr, takeRef) { if (ptr != NULL) { - list > *listeners = new list >; - belle_sip_object_data_set(ptr, sListenerListName.c_str(), listeners, (belle_sip_data_destroy)deleteListenerList); + if (belle_sip_object_data_get(ptr, sListenerListName.c_str()) == NULL) { + list > *listeners = new list >; + belle_sip_object_data_set(ptr, sListenerListName.c_str(), listeners, (belle_sip_data_destroy)deleteListenerList); + } } } -MultiListenableObject::~MultiListenableObject() { - if (mPrivPtr != NULL) { - belle_sip_object_data_set(mPrivPtr, sListenerListName.c_str(), NULL, NULL); - } +std::list > &MultiListenableObject::getListeners() const { + return *(std::list > *)belle_sip_object_data_get(mPrivPtr, sListenerListName.c_str()); } void MultiListenableObject::addListener(const std::shared_ptr &listener) { diff --git a/wrappers/cpp/object.hh b/wrappers/cpp/object.hh index 0c7baa236..3d41db0ea 100644 --- a/wrappers/cpp/object.hh +++ b/wrappers/cpp/object.hh @@ -141,22 +141,7 @@ namespace linphone { }; - class Listener { - public: - Listener(): mCbs(NULL) {} - virtual ~Listener() {setCallbacks(NULL);} - - public: - void setCallbacks(::belle_sip_object_t *cbs) { - if (mCbs != NULL) belle_sip_object_unref(mCbs); - if (cbs == NULL) mCbs = NULL; - else mCbs = belle_sip_object_ref(cbs); - } - belle_sip_object_t *getCallbacks() {return mCbs;} - - private: - ::belle_sip_object_t *mCbs; - }; + class Listener {}; class ListenableObject: public Object { @@ -179,11 +164,12 @@ namespace linphone { protected: MultiListenableObject(::belle_sip_object_t *ptr, bool takeRef=true); - virtual ~MultiListenableObject(); + virtual ~MultiListenableObject() {}; protected: void addListener(const std::shared_ptr &listener); void removeListener(const std::shared_ptr &listener); + std::list > &getListeners() const; private: static void deleteListenerList(std::list > *listeners) {delete listeners;}