Commit 3f2cbf6e authored by François Grisez's avatar François Grisez
Browse files

C++ wrapper: reworking of multilstenable classes

There is now only one LinphoneCoreCbs instance attached to the core
that is in charge to collect all events for the C++ wrapper layer.
Thus, it is the concern of the C++ wrapper to dispach events to all
the C++ listeners.
parent 17df3b86
......@@ -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<Core> createCore(const std::shared_ptr<CoreListener> & cbs, const std::string & configPath, const std::string & factoryConfigPath) const;
LINPHONECXX_PUBLIC std::shared_ptr<Core> createCoreWithConfig(const std::shared_ptr<CoreListener> & cbs, const std::shared_ptr<Config> & config) const;
LINPHONECXX_PUBLIC std::shared_ptr<Core> createCore(const std::shared_ptr<CoreListener> &listener, const std::string & configPath, const std::string & factoryConfigPath) const;
LINPHONECXX_PUBLIC std::shared_ptr<Core> createCoreWithConfig(const std::shared_ptr<CoreListener> &listener, const std::shared_ptr<Config> & config) const;
{{/isfactory}}
{{#isVcard}}
LINPHONECXX_PUBLIC std::shared_ptr<belcard::BelCard> &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}}
......
......@@ -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) {
{{{cListenerName}}} *cbs = {{{listenerCreator}}}(linphone_factory_get());
{{{userDataSetter}}}(cbs, listener.get());
{{#wrapperCbs}}
{{{callbackSetter}}}(cbs, {{{cbName}}});
{{/wrapperCbs}}
return cbs;
{{{className}}}::~{{{className}}}() {
{{{callbacksRemover}}}(({{{cClassName}}} *)mPrivPtr, mCallbacks);
belle_sip_object_unref(mCallbacks);
}
void {{{className}}}::addListener(std::shared_ptr<{{{listenerClassName}}}> &listener) {
void {{{className}}}::addListener(const std::shared_ptr<{{{listenerClassName}}}> &listener) {
MultiListenableObject::addListener(std::static_pointer_cast<Listener,{{{listenerClassName}}}>(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);
void {{{className}}}::removeListener(const std::shared_ptr<{{{listenerClassName}}}> &listener) {
MultiListenableObject::removeListener(std::static_pointer_cast<Listener,{{{listenerClassName}}}>(listener));
}
{{{cListenerName}}} *{{{className}}}::createCallbacks(void *userData) {
{{{cListenerName}}} *cbs = {{{listenerCreator}}}(linphone_factory_get());
{{#wrapperCbs}}
{{{callbackSetter}}}(cbs, {{{cbName}}});
{{/wrapperCbs}}
{{{userDataSetter}}}(cbs, userData);
return cbs;
}
{{/ismultilistenable}}
{{#isfactory}}
std::shared_ptr<Core> Factory::createCore(const std::shared_ptr<CoreListener> & cbs, const std::string & configPath, const std::string & factoryConfigPath) const {
std::shared_ptr<Core> Factory::createCore(const std::shared_ptr<CoreListener> & listener, const std::string & configPath, const std::string & factoryConfigPath) const {
::LinphoneCoreCbs *cbs = NULL;
if (listener != nullptr) {
std::list<std::shared_ptr<Listener> > listeners;
listeners.push_back(std::static_pointer_cast<Listener,CoreListener>(listener));
cbs = Core::createCallbacks(&listeners);
}
::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> core = cPtrToSharedPtr<Core>((belle_sip_object_t *)core_ptr, false);
if (core != nullptr && cbs != nullptr) {
std::static_pointer_cast<MultiListenableObject,Core>(core)->addListener(cbs);
cbs->setCallbacks((belle_sip_object_t *)c_cbs);
::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);
}
if (c_cbs) linphone_core_cbs_unref(c_cbs);
return core;
std::shared_ptr<Core> cppCore = cPtrToSharedPtr<Core>((::belle_sip_object_t *)core_ptr, false);
if (listener != nullptr) cppCore->addListener(listener);
return cppCore;
}
std::shared_ptr<Core> Factory::createCoreWithConfig(const std::shared_ptr<CoreListener> & cbs, const std::shared_ptr<Config> & config) const {
std::shared_ptr<Core> Factory::createCoreWithConfig(const std::shared_ptr<CoreListener> & listener, const std::shared_ptr<Config> & config) const {
::LinphoneCoreCbs *cbs = NULL;
if (listener != nullptr) {
std::list<std::shared_ptr<Listener> > listeners;
listeners.push_back(std::static_pointer_cast<Listener,CoreListener>(listener));
cbs = Core::createCallbacks(&listeners);
}
::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> core = cPtrToSharedPtr<Core>((belle_sip_object_t *)core_ptr, false);
if (core != nullptr && cbs != nullptr) {
std::static_pointer_cast<MultiListenableObject,Core>(core)->addListener(cbs);
cbs->setCallbacks((belle_sip_object_t *)c_cbs);
::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);
}
if (c_cbs) linphone_core_cbs_unref(c_cbs);
return core;
std::shared_ptr<Core> cppCore = cPtrToSharedPtr<Core>((::belle_sip_object_t *)core_ptr, false);
if (listener != nullptr) cppCore->addListener(listener);
return cppCore;
}
{{/isfactory}}
......@@ -118,12 +135,19 @@ std::shared_ptr<belcard::BelCard> &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}}
{{#ismonolistenable}}
std::shared_ptr<{{{cppListenerName}}}> listener = std::static_pointer_cast<{{{cppListenerName}}},Listener>(getListenerFromObject((::belle_sip_object_t *){{{firstArgName}}}));
{{#hasReturnValue}}return {{/hasReturnValue}}{{{cppMethodCallingLine}}};
{{/ismonolistenable}}
{{#ismultilistenable}}
LinphoneCoreCbs *cbs = linphone_core_get_current_callbacks(lc);
CoreListener *listener = (CoreListener *)linphone_core_cbs_get_user_data(cbs);
{{{cListenerName}}} *cbs = {{{currentCallbacksGetter}}}({{{firstArgName}}});
std::list<std::shared_ptr<Listener> > &listeners = *(std::list<std::shared_ptr<Listener> > *){{{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}}
{{#hasReturnValue}}return {{/hasReturnValue}}{{{cppMethodCallingLine}}};
}
{{/wrapperCbs}}
......
......@@ -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:
......
......@@ -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<shared_ptr<Listener> > *listeners = new list<shared_ptr<Listener> >;
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<shared_ptr<Listener> > *listeners = new list<shared_ptr<Listener> >;
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<std::shared_ptr<Listener> > &MultiListenableObject::getListeners() const {
return *(std::list<std::shared_ptr<Listener> > *)belle_sip_object_data_get(mPrivPtr, sListenerListName.c_str());
}
void MultiListenableObject::addListener(const std::shared_ptr<Listener> &listener) {
......
......@@ -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> &listener);
void removeListener(const std::shared_ptr<Listener> &listener);
std::list<std::shared_ptr<Listener> > &getListeners() const;
private:
static void deleteListenerList(std::list<std::shared_ptr<Listener> > *listeners) {delete listeners;}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment