diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index 01cd7fd79f2ee94bcfe3e2caf19666301d5c8bc9..f2b56c39f29d2fa84dcbc4385e2e216586eacf31 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -1108,8 +1108,9 @@ static void refer_received(SalOp *op, const SalAddress *refer_to) {
 					}
 				} else {
 					if (!participant) {
-						bool ret = static_pointer_cast<MediaConference::LocalConference>(conference)
-						               ->addParticipant(referAddr);
+						auto participantInfo = Factory::get()->createParticipantInfo(referAddr);
+						participantInfo->setRole(Participant::Role::Speaker);
+						bool ret = conference->addParticipant(participantInfo);
 						static_cast<SalReferOp *>(op)->reply(ret ? SalReasonNone : SalReasonNotAcceptable);
 						return;
 					}
diff --git a/coreapi/conference.cpp b/coreapi/conference.cpp
index e0796feb737e53a73b98809ad6f6a25e7e3fb9d6..94c4ce899883c0dd3c3aa7aaf260183acf0081d2 100644
--- a/coreapi/conference.cpp
+++ b/coreapi/conference.cpp
@@ -231,6 +231,19 @@ void Conference::fillParticipantAttributes(std::shared_ptr<Participant> &p) {
 			           "therefoe participant "
 			        << *pAddress << " is given the role of " << p->getRole();
 		} else {
+			const bool isThereAListener =
+			    std::find_if(mInvitedParticipants.cbegin(), mInvitedParticipants.cend(), [](const auto &info) {
+				    return (info->getRole() == Participant::Role::Listener);
+			    }) != mInvitedParticipants.cend();
+
+			Participant::Role role = Participant::Role::Unknown;
+			if (isThereAListener) {
+				role = Participant::Role::Listener;
+			} else {
+				role = Participant::Role::Speaker;
+			}
+			p->setRole(role);
+
 			lInfo() << "Unable to find participant " << *pAddress
 			        << " in the list of invited participants. Assuming its role to be " << p->getRole()
 			        << " in conference " << this << " (address " << conferenceAddressStr << ")";
@@ -248,6 +261,11 @@ void Conference::fillParticipantAttributes(std::shared_ptr<Participant> &p) {
 	}
 }
 
+bool Conference::addParticipant(BCTBX_UNUSED(const std::shared_ptr<ParticipantInfo> &info)) {
+	lError() << "Conference class does not handle addParticipant() generically";
+	return false;
+}
+
 bool Conference::addParticipant(const std::shared_ptr<Address> &participantAddress) {
 	bool success = LinphonePrivate::Conference::addParticipant(participantAddress);
 
diff --git a/coreapi/conference.h b/coreapi/conference.h
index f17ebfbfc368b1f710f2c061e4f4d680cd247f19..f03047c86a07921313fe265e2a5961c9f9a1da37 100644
--- a/coreapi/conference.h
+++ b/coreapi/conference.h
@@ -100,6 +100,7 @@ public:
 	                            const LinphoneCallParams *params) = 0;
 	virtual bool dialOutAddresses(const std::list<std::shared_ptr<Address>> &addressList) = 0;
 	virtual bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
+	virtual bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override;
 	virtual bool addParticipant(std::shared_ptr<LinphonePrivate::Call> call) override;
 	virtual bool finalizeParticipantAddition(std::shared_ptr<LinphonePrivate::Call> call) = 0;
 
diff --git a/coreapi/local_conference.cpp b/coreapi/local_conference.cpp
index f3071c6df1f7f720fc6f31fc51b3908f737c25dd..71d73d7889270b64abe19d724df73d860771f837 100644
--- a/coreapi/local_conference.cpp
+++ b/coreapi/local_conference.cpp
@@ -1353,6 +1353,13 @@ bool LocalConference::addParticipant(std::shared_ptr<LinphonePrivate::Call> call
 }
 
 bool LocalConference::addParticipant(const std::shared_ptr<Address> &participantAddress) {
+	auto participantInfo = Factory::get()->createParticipantInfo(participantAddress);
+	// Participants invited after the start of a conference through the address can only listen to it
+	participantInfo->setRole(Participant::Role::Listener);
+	return addParticipant(participantInfo);
+}
+
+bool LocalConference::addParticipant(const std::shared_ptr<ParticipantInfo> &info) {
 #if 0
 	if (!isConferenceEnded() && isConferenceStarted()) {
 #endif
@@ -1361,14 +1368,14 @@ bool LocalConference::addParticipant(const std::shared_ptr<Address> &participant
 	    (initialState == ConferenceInterface::State::Created)) {
 
 		const auto allowedAddresses = getAllowedAddresses();
+		const auto &participantAddress = info->getAddress();
 		auto p =
 		    std::find_if(allowedAddresses.begin(), allowedAddresses.end(), [&participantAddress](const auto &address) {
 			    return (participantAddress->weakEqual(*address));
 		    });
 		if (p == allowedAddresses.end()) {
-			// Participants invited after the start of a conference can only listen to it
-			auto participantInfo = Factory::get()->createParticipantInfo(participantAddress);
-			participantInfo->setRole(Participant::Role::Listener);
+			auto participantInfo = info->clone()->toSharedPtr();
+			participantInfo->setSequenceNumber(-1);
 			mInvitedParticipants.push_back(participantInfo);
 		}
 
diff --git a/coreapi/local_conference.h b/coreapi/local_conference.h
index e004259f5432436b40a5392479f38d66d8273e53..1462b0c3f223bbd9943da95569525b220d842067 100644
--- a/coreapi/local_conference.h
+++ b/coreapi/local_conference.h
@@ -54,6 +54,7 @@ public:
 	virtual bool addParticipants(const std::list<std::shared_ptr<LinphonePrivate::Call>> &call) override;
 	virtual bool addParticipants(const std::list<std::shared_ptr<Address>> &addresses) override;
 	virtual bool addParticipant(std::shared_ptr<LinphonePrivate::Call> call) override;
+	virtual bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override;
 	virtual bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
 	virtual bool finalizeParticipantAddition(std::shared_ptr<LinphonePrivate::Call> call) override;
 	virtual bool addParticipantDevice(std::shared_ptr<LinphonePrivate::Call> call) override;
diff --git a/coreapi/remote_conference.cpp b/coreapi/remote_conference.cpp
index ef830fab7692c4403c40b5c96237a1b1bd56c486..eac19f4c0b76113d3d281e9ba22733471c7ed60d 100644
--- a/coreapi/remote_conference.cpp
+++ b/coreapi/remote_conference.cpp
@@ -165,6 +165,28 @@ void RemoteConference::finalizeCreation() {
 	}
 }
 
+void RemoteConference::updateAndSaveConferenceInformations() {
+	const auto conferenceInfo = getUpdatedConferenceInfo();
+	long long conferenceInfoId = -1;
+
+#ifdef HAVE_DB_STORAGE
+	// Store into DB after the start incoming notification in order to have a valid conference address being the contact
+	// address of the call
+	auto &mainDb = getCore()->getPrivate()->mainDb;
+	if (mainDb) {
+		lInfo() << "Inserting or updating conference information to database related to conference "
+		        << *getConferenceAddress();
+		conferenceInfoId = mainDb->insertConferenceInfo(conferenceInfo);
+	}
+#endif // HAVE_DB_STORAGE
+
+	auto callLog = getMainSession() ? getMainSession()->getLog() : nullptr;
+	if (callLog) {
+		callLog->setConferenceInfo(conferenceInfo);
+		callLog->setConferenceInfoId(conferenceInfoId);
+	}
+}
+
 std::shared_ptr<ConferenceInfo> RemoteConference::createConferenceInfo() const {
 	auto session = static_pointer_cast<MediaSession>(getMainSession());
 	const auto referer = (session ? L_GET_PRIVATE(session->getMediaParams())->getReferer() : nullptr);
@@ -378,6 +400,11 @@ bool RemoteConference::addParticipantDevice(std::shared_ptr<LinphonePrivate::Cal
 	return success;
 }
 
+bool RemoteConference::addParticipant(BCTBX_UNUSED(const std::shared_ptr<ParticipantInfo> &info)) {
+	lError() << "addParticipant() with a participant info is not allowed on a RemoteConference";
+	return false;
+}
+
 bool RemoteConference::addParticipant(const std::shared_ptr<Address> &participantAddress) {
 	// Search call that matches participant session
 	const std::list<std::shared_ptr<Call>> &coreCalls = getCore()->getCalls();
@@ -1271,22 +1298,12 @@ void RemoteConference::onParticipantAdded(const shared_ptr<ConferenceParticipant
                                           const std::shared_ptr<Participant> &participant) {
 	const std::shared_ptr<Address> &pAddr = event->getParticipantAddress();
 
+	lInfo() << "Updating conference information of conference " << *getConferenceAddress()
+	        << " because the core has been notified that participat " << *participant->getAddress()
+	        << " has been added";
 	// When receiving a participant added notification, we must recreate the conference informations in order to get the
 	// participant list up to date
-	const auto conferenceInfo = getUpdatedConferenceInfo();
-	auto callLog = getMainSession() ? getMainSession()->getLog() : nullptr;
-	if (callLog) {
-		callLog->setConferenceInfo(conferenceInfo);
-	}
-
-#ifdef HAVE_DB_STORAGE
-	auto &mainDb = getCore()->getPrivate()->mainDb;
-	if (mainDb) {
-		lInfo() << "Updating conference information of conference " << *getConferenceAddress()
-		        << " because participant " << *pAddr << " has been added to the conference";
-		mainDb->insertConferenceInfo(conferenceInfo);
-	}
-#endif // HAVE_DB_STORAGE
+	updateAndSaveConferenceInformations();
 
 	if (isMe(pAddr)) {
 		if (getState() == ConferenceInterface::State::CreationPending) {
@@ -1319,36 +1336,22 @@ void RemoteConference::onParticipantAdded(const shared_ptr<ConferenceParticipant
 }
 
 void RemoteConference::onSubjectChanged(BCTBX_UNUSED(const std::shared_ptr<ConferenceSubjectEvent> &event)) {
-	const auto conferenceInfo = createOrGetConferenceInfo();
-	auto callLog = getMainSession() ? getMainSession()->getLog() : nullptr;
-	if (callLog) {
-		callLog->setConferenceInfo(conferenceInfo);
-	}
+	lInfo() << "Updating conference information of conference " << *getConferenceAddress()
+	        << " because the core has been notified that the subject has been changed to " << getSubject();
+	updateAndSaveConferenceInformations();
 }
 
 void RemoteConference::onParticipantSetRole(BCTBX_UNUSED(const std::shared_ptr<ConferenceParticipantEvent> &event),
-                                            BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
-
-	updateParticipantRoleInConferenceInfo(participant);
-	const auto conferenceInfo = createOrGetConferenceInfo();
-	auto callLog = getMainSession() ? getMainSession()->getLog() : nullptr;
-	if (callLog) {
-		callLog->setConferenceInfo(conferenceInfo);
-	}
+                                            const std::shared_ptr<Participant> &participant) {
+	lInfo() << "Updating conference information of conference " << *getConferenceAddress()
+	        << " because the core has been notified that participat " << *participant->getAddress()
+	        << " has changed its role to " << participant->getRole();
+	updateAndSaveConferenceInformations();
 }
 
 void RemoteConference::onParticipantRemoved(const shared_ptr<ConferenceParticipantEvent> &event,
                                             BCTBX_UNUSED(const std::shared_ptr<Participant> &participant)) {
 	const std::shared_ptr<Address> &pAddr = event->getParticipantAddress();
-
-	// When receiving a participant removed notification, we must recreate the conference informations in order to get
-	// the security level and the participant list up to date
-	const auto conferenceInfo = createOrGetConferenceInfo();
-	auto callLog = getMainSession() ? getMainSession()->getLog() : nullptr;
-	if (callLog) {
-		callLog->setConferenceInfo(conferenceInfo);
-	}
-
 	if (isMe(pAddr)) {
 		lInfo() << "Unsubscribing all devices of me (address " << *pAddr << ") from conference "
 		        << *getConferenceAddress();
@@ -1477,24 +1480,7 @@ void RemoteConference::onParticipantDeviceMediaAvailabilityChanged(
 void RemoteConference::onFullStateReceived() {
 	// When receiving a full state, we must recreate the conference informations in order to get the security level and
 	// the participant list up to date
-	const auto conferenceInfo = getUpdatedConferenceInfo();
-	long long conferenceInfoId = -1;
-
-#ifdef HAVE_DB_STORAGE
-	// Store into DB after the start incoming notification in order to have a valid conference address being the contact
-	// address of the call
-	auto &mainDb = getCore()->getPrivate()->mainDb;
-	if (mainDb) {
-		lInfo() << "Inserting conference information to database related to conference " << *getConferenceAddress();
-		conferenceInfoId = mainDb->insertConferenceInfo(conferenceInfo);
-	}
-#endif // HAVE_DB_STORAGE
-
-	auto callLog = getMainSession() ? getMainSession()->getLog() : nullptr;
-	if (callLog) {
-		callLog->setConferenceInfo(conferenceInfo);
-		callLog->setConferenceInfoId(conferenceInfoId);
-	}
+	updateAndSaveConferenceInformations();
 
 	auto requestStreams = [this]() -> LinphoneStatus {
 		lInfo() << "Sending re-INVITE in order to get streams after joining conference " << *getConferenceAddress();
diff --git a/coreapi/remote_conference.h b/coreapi/remote_conference.h
index 7d6e72d120644d7679221964969c860f1e84212d..4bc2a3d79535607795f8fa61ebf0825341282755 100644
--- a/coreapi/remote_conference.h
+++ b/coreapi/remote_conference.h
@@ -61,6 +61,7 @@ public:
 	virtual int inviteAddresses(const std::list<std::shared_ptr<Address>> &addresses,
 	                            const LinphoneCallParams *params) override;
 	virtual bool dialOutAddresses(const std::list<std::shared_ptr<Address>> &addressList) override;
+	virtual bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override;
 	virtual bool addParticipants(const std::list<std::shared_ptr<LinphonePrivate::Call>> &call) override;
 	virtual bool addParticipants(const std::list<std::shared_ptr<Address>> &addresses) override;
 	virtual bool addParticipant(std::shared_ptr<LinphonePrivate::Call> call) override;
@@ -171,6 +172,7 @@ protected:
 private:
 	virtual const std::shared_ptr<CallSession> getMainSession() const override;
 	virtual std::shared_ptr<ConferenceInfo> createConferenceInfo() const override;
+	void updateAndSaveConferenceInformations();
 	bool focusIsReady() const;
 	bool transferToFocus(std::shared_ptr<LinphonePrivate::Call> call);
 	void reset();
diff --git a/src/call/call-log.cpp b/src/call/call-log.cpp
index 6762ce1ca6de6d051b36403e7ef7bdeb5d11e0c1..c8e62aab8419880b8a5fdb0118896f7303c38c1f 100644
--- a/src/call/call-log.cpp
+++ b/src/call/call-log.cpp
@@ -212,9 +212,17 @@ std::shared_ptr<ConferenceInfo> &CallLog::getConferenceInfo() {
 	// The conference info stored in the database is always up to date, therefore try to update the cache all the time
 	// if there id is valid Nonetheless, the cache variable is required if the core disables the storage of information
 	// in the database.
+#ifdef HAVE_DB_STORAGE
+	auto &db = L_GET_PRIVATE(getCore())->mainDb;
 	if (mConferenceInfoId != -1) {
-		setConferenceInfo(L_GET_PRIVATE(getCore())->mainDb->getConferenceInfo(mConferenceInfoId));
+		setConferenceInfo(db->getConferenceInfo(mConferenceInfoId));
+	} else if (mTo && !mConferenceInfo) {
+		// Try to find the conference info based on the to address
+		// We enter this branch of the if-else statement only if the call cannot be started right away, for example when
+		// ICE candidates need to be gathered first
+		setConferenceInfo(db->getConferenceInfoFromURI(mTo));
 	}
+#endif // HAVE_DB_STORAGE
 
 	return mConferenceInfo;
 }
diff --git a/src/chat/chat-room/basic-chat-room.cpp b/src/chat/chat-room/basic-chat-room.cpp
index ba2dfa395973521ebe8ce5bd7df75b34e9ea53e3..abf3509a3dd76587a6bae45c193cc3d5f447034f 100644
--- a/src/chat/chat-room/basic-chat-room.cpp
+++ b/src/chat/chat-room/basic-chat-room.cpp
@@ -105,6 +105,11 @@ const std::shared_ptr<Address> &BasicChatRoom::getConferenceAddress() const {
 	return Utils::getEmptyConstRefObject<std::shared_ptr<Address>>();
 }
 
+bool BasicChatRoom::addParticipant(BCTBX_UNUSED(const std::shared_ptr<ParticipantInfo> &info)) {
+	lError() << "addParticipant() is not allowed on a BasicChatRoom";
+	return false;
+}
+
 bool BasicChatRoom::addParticipant(BCTBX_UNUSED(std::shared_ptr<Call> call)) {
 	lError() << "addParticipant() is not allowed on a BasicChatRoom";
 	return false;
diff --git a/src/chat/chat-room/basic-chat-room.h b/src/chat/chat-room/basic-chat-room.h
index e3128dca300ffb64b8f25e687d61e8345ce15b75..77d84bdc4d81e69522a122e04e1e1c65dc3135d1 100644
--- a/src/chat/chat-room/basic-chat-room.h
+++ b/src/chat/chat-room/basic-chat-room.h
@@ -72,6 +72,7 @@ public:
 
 	bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
 	bool addParticipant(std::shared_ptr<Call> call) override;
+	bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override;
 	bool addParticipants(const std::list<std::shared_ptr<Address>> &addresses) override;
 	void join(const std::shared_ptr<Address> &participantAddress) override;
 	bool update(const ConferenceParamsInterface &newParameters) override;
diff --git a/src/chat/chat-room/client-group-chat-room.h b/src/chat/chat-room/client-group-chat-room.h
index 17323e70ba1593e6f3672acf5a3b6ad658319a74..150e808f97715452b93eb4380f72b1d6ec08af09 100644
--- a/src/chat/chat-room/client-group-chat-room.h
+++ b/src/chat/chat-room/client-group-chat-room.h
@@ -69,6 +69,10 @@ public:
 	int getHistorySize() const override;
 
 	bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
+	bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override {
+		return getConference()->addParticipant(info);
+	};
+
 	bool addParticipant(std::shared_ptr<Call> call) override {
 		return getConference()->addParticipant(call);
 	};
diff --git a/src/chat/chat-room/proxy-chat-room.cpp b/src/chat/chat-room/proxy-chat-room.cpp
index 5bf0a671a89457c733ba23e18eceb544d60c6877..fe9bdf650b44aa2caecae9b0e0d2b21cb8cbd4e3 100644
--- a/src/chat/chat-room/proxy-chat-room.cpp
+++ b/src/chat/chat-room/proxy-chat-room.cpp
@@ -313,6 +313,11 @@ bool ProxyChatRoom::canHandleMultipart() const {
 	return d->chatRoom->canHandleMultipart();
 }
 
+bool ProxyChatRoom::addParticipant(const std::shared_ptr<ParticipantInfo> &info) {
+	L_D();
+	return d->chatRoom->addParticipant(info);
+};
+
 bool ProxyChatRoom::addParticipant(std::shared_ptr<Call> call) {
 	L_D();
 	return d->chatRoom->addParticipant(call);
diff --git a/src/chat/chat-room/proxy-chat-room.h b/src/chat/chat-room/proxy-chat-room.h
index dec301939dbe37ce196751cc14e3d447e30148d4..8a69f72e6334aeee7cbe78e20c828b6224c11772 100644
--- a/src/chat/chat-room/proxy-chat-room.h
+++ b/src/chat/chat-room/proxy-chat-room.h
@@ -134,6 +134,7 @@ public:
 
 	bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
 	bool addParticipant(std::shared_ptr<Call> call) override;
+	bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override;
 	bool addParticipants(const std::list<std::shared_ptr<Address>> &addresses) override;
 	bool isMe(const std::shared_ptr<Address> &address) const override;
 
diff --git a/src/chat/chat-room/server-group-chat-room.h b/src/chat/chat-room/server-group-chat-room.h
index d7bb3d64b4b11d2113cd59d55051fb9dee7b32b4..da45048c2983db15ba54dc25be6d595a3a08effd 100644
--- a/src/chat/chat-room/server-group-chat-room.h
+++ b/src/chat/chat-room/server-group-chat-room.h
@@ -59,6 +59,9 @@ public:
 	const std::shared_ptr<Address> &getConferenceAddress() const override;
 
 	bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
+	bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override {
+		return getConference()->addParticipant(info);
+	};
 	bool addParticipant(std::shared_ptr<Call> call) override {
 		return getConference()->addParticipant(call);
 	};
diff --git a/src/conference/conference-info.cpp b/src/conference/conference-info.cpp
index 69b4f66b89fbda0c09b1077f7410c851d5d79e09..87362e7e9185ae52c809be4f57f3c67459f748d0 100644
--- a/src/conference/conference-info.cpp
+++ b/src/conference/conference-info.cpp
@@ -123,9 +123,9 @@ void ConferenceInfo::addParticipant(const std::shared_ptr<const ParticipantInfo>
 			newInfo = participantInfo->clone()->toSharedPtr();
 		}
 		mParticipants.push_back(newInfo);
-		lInfo() << "Participant with address " << *address << " has been added to conference info " << this
-		        << " (address " << (getUri() ? getUri()->toString() : std::string("<unknown address>"))
-		        << ") with role " << newInfo->getRole();
+		lDebug() << "Participant with address " << *address << "has been added to conference info " << this
+		         << " (address " << (getUri() ? getUri()->toString() : std::string("<unknown address>"))
+		         << ") with role " << newInfo->getRole();
 	} else {
 		lInfo() << "Participant with address " << *address << " is already in the list of conference info " << this
 		        << " (address " << (getUri() ? getUri()->toString() : std::string("<unknown address>")) << ")";
@@ -144,8 +144,8 @@ void ConferenceInfo::removeParticipant(const std::shared_ptr<const ParticipantIn
 void ConferenceInfo::removeParticipant(const std::shared_ptr<const Address> &participant) {
 	auto it = findParticipantIt(participant);
 	if (it == mParticipants.cend()) {
-		lInfo() << "Unable to remove participant with address " << *participant << " in conference info " << this
-		        << " (address " << (getUri() ? getUri()->toString() : std::string("<unknown address>")) << ")";
+		lDebug() << "Unable to remove participant with address " << *participant << " in conference info " << this
+		         << " (address " << (getUri() ? getUri()->toString() : std::string("<unknown address>")) << ")";
 	} else {
 		lInfo() << "Participant with address " << *participant << " has been removed from conference info " << this
 		        << " (address " << (getUri() ? getUri()->toString() : std::string("<unknown address>")) << ")";
diff --git a/src/conference/conference-interface.h b/src/conference/conference-interface.h
index cf45b8dd520f420dd7831f3885abc71a81c20964..19da7342bc12955b04697e213593b73a759e2b35 100644
--- a/src/conference/conference-interface.h
+++ b/src/conference/conference-interface.h
@@ -165,11 +165,19 @@ public:
 	/*
 	 * Same as function addParticipant(const std::shared_ptr<Address> &participantAddress), except that call to add is
 	 * passed by the user application.
-	 * @param[in] call to be added tot he conference.
+	 * @param[in] call to be added to the conference.
 	 * @return True if everything is OK, False otherwise
 	 */
 	virtual bool addParticipant(std::shared_ptr<Call> call) = 0;
 
+	/*
+	 * Same as function addParticipant(const std::shared_ptr<Address> &participantAddress), except the participant
+	 * information to add is passed by the user application.
+	 * @param[in] participant information to be added to the conference.
+	 * @return True if everything is OK, False otherwise
+	 */
+	virtual bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) = 0;
+
 	/*
 	 * Add several participants at once.
 	 * @param[in] addresses
diff --git a/src/conference/conference.cpp b/src/conference/conference.cpp
index ddaa61cad5ba954f9e7c063005b06efd654cba6f..1890f121a25560329a665c0074470a1e5ba24e50 100644
--- a/src/conference/conference.cpp
+++ b/src/conference/conference.cpp
@@ -86,6 +86,11 @@ void Conference::clearParticipants() {
 
 // -----------------------------------------------------------------------------
 
+bool Conference::addParticipant(BCTBX_UNUSED(const std::shared_ptr<ParticipantInfo> &info)) {
+	lError() << "Conference class does not handle addParticipant() generically";
+	return false;
+}
+
 bool Conference::addParticipant(BCTBX_UNUSED(std::shared_ptr<Call> call)) {
 	lError() << "Conference class does not handle addParticipant() generically";
 	return false;
@@ -282,7 +287,6 @@ void Conference::setUtf8Subject(const string &subject) {
 
 void Conference::setSubject(const string &subject) {
 	confParams->setSubject(subject);
-	updateSubjectInConferenceInfo(subject);
 }
 
 shared_ptr<ConferenceParticipantDeviceEvent>
diff --git a/src/conference/conference.h b/src/conference/conference.h
index f53956b69aa6a0aed5d0475cc7157cfa8fcc5895..8ca05371e44aae4fa27d44e5d1a9bfb181828ed6 100644
--- a/src/conference/conference.h
+++ b/src/conference/conference.h
@@ -91,6 +91,7 @@ public:
 	std::shared_ptr<Participant> getMe() const override;
 	bool isMe(const std::shared_ptr<Address> &addr) const;
 	bool addParticipant(std::shared_ptr<Call> call) override;
+	bool addParticipant(const std::shared_ptr<ParticipantInfo> &info) override;
 	bool addParticipant(const std::shared_ptr<Address> &participantAddress) override;
 	bool addParticipants(const std::list<std::shared_ptr<Address>> &addresses) override;
 	int getParticipantCount() const override;
diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp
index 5791ddf383967e930593d4f25154d93f68afac73..303534eb0b9d686dc2d59a82168fb124a42f6f2a 100644
--- a/src/conference/handlers/local-conference-event-handler.cpp
+++ b/src/conference/handlers/local-conference-event-handler.cpp
@@ -1197,7 +1197,9 @@ void LocalConferenceEventHandler::onParticipantSetAdmin(const std::shared_ptr<Co
 void LocalConferenceEventHandler::onSubjectChanged(const std::shared_ptr<ConferenceSubjectEvent> &event) {
 	// Do not send notify if conference pointer is null. It may mean that the confernece has been terminated
 	if (conf) {
-		notifyAll(makeContent(createNotifySubjectChanged(event->getSubject())));
+		const auto &subject = event->getSubject();
+		conf->updateSubjectInConferenceInfo(subject);
+		notifyAll(makeContent(createNotifySubjectChanged(subject)));
 		if (conf) {
 			shared_ptr<Core> core = conf->getCore();
 			std::shared_ptr<Address> conferenceAddress = conf->getConferenceAddress();
diff --git a/src/conference/handlers/remote-conference-event-handler.cpp b/src/conference/handlers/remote-conference-event-handler.cpp
index a782dec7d7ab06ca4fb8c7d3dcd2c264c5bdbc5c..ca67637038076c3f694645887888e19816efa49a 100644
--- a/src/conference/handlers/remote-conference-event-handler.cpp
+++ b/src/conference/handlers/remote-conference-event-handler.cpp
@@ -274,7 +274,6 @@ void RemoteConferenceEventHandler::conferenceInfoNotifyReceived(const string &xm
 				auto securityLevelString = cryptoSecurityLevel.getLevel();
 				auto securityLevel = ConferenceParams::getSecurityLevelFromAttribute(securityLevelString);
 				conf->confParams->setSecurityLevel(securityLevel);
-				conf->updateSecurityLevelInConferenceInfo(securityLevel);
 			}
 		}
 	}
diff --git a/src/core/core-call.cpp b/src/core/core-call.cpp
index 332f4c41ed751810484df0598a0d14fc359a3fce..f86f013bd604d11e6cacd966fd0ac7ab1583ba50 100644
--- a/src/core/core-call.cpp
+++ b/src/core/core-call.cpp
@@ -342,7 +342,6 @@ void Core::reportConferenceCallEvent(EventLog::Type type,
                                      std::shared_ptr<CallLog> &callLog,
                                      std::shared_ptr<ConferenceInfo> confInfo) {
 	std::shared_ptr<Address> to = callLog->getToAddress() ? callLog->getToAddress() : nullptr;
-	// TODO: This is a workaround that has to be removed ASAP
 #ifdef HAVE_DB_STORAGE
 	L_D();
 
@@ -354,6 +353,7 @@ void Core::reportConferenceCallEvent(EventLog::Type type,
 	}
 #endif
 
+	// TODO: This is a workaround that has to be removed ASAP
 	// Add all calls that have been into a conference to the call logs of the core. The if below is required for calls
 	// that have been merged in a conference. In fact, in such a scenario, the client that merges calls to put them in a
 	// conference will call the conference factory or the audio video conference factory directly but still its call
diff --git a/tester/local_conference_tester_functions.cpp b/tester/local_conference_tester_functions.cpp
index d5da877468c4daa5131d5c2101c99e951ab8c2c1..cb2a3cc52edb0e6de3cdb7825bec12449cb5396a 100644
--- a/tester/local_conference_tester_functions.cpp
+++ b/tester/local_conference_tester_functions.cpp
@@ -1026,33 +1026,6 @@ void group_chat_room_with_sip_errors_base(bool invite_error, bool subscribe_erro
 		BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 4, int, "%d");
 		BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(bertheCr), 4, int, "%d");
 
-		/*
-		        LinphoneAddress *michelle2Contact =
-		   linphone_address_clone(linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(michelle2.getLc())));
-		        ms_message("%s is restarting its core", linphone_address_as_string(michelle2Contact));
-		        linphone_address_unref(michelle2Contact);
-		        initialFocusStats = focus.getStats();
-		        coresList = bctbx_list_remove(coresList, michelle2.getLc());
-		        //Restart michelle
-		        michelle2.reStart();
-		        setup_mgr_for_conference(michelle2.getCMgr(), NULL);
-		        coresList = bctbx_list_append(coresList, michelle2.getLc());
-
-		        BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneRegistrationOk, 1,
-		   liblinphone_tester_sip_timeout)); if (encrypted) {
-		            BC_ASSERT_TRUE(linphone_core_lime_x3dh_enabled(michelle2.getLc()));
-		        }
-		        BC_ASSERT_TRUE(wait_for_list(coresList, &michelle2.getStats().number_of_LinphoneConferenceStateCreated,
-		   1, liblinphone_tester_sip_timeout)); BC_ASSERT_TRUE(wait_for_list(coresList,
-		   &michelle2.getStats().number_of_LinphoneSubscriptionActive, 1, liblinphone_tester_sip_timeout));
-		        BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_LinphoneSubscriptionActive,
-		   initialFocusStats.number_of_LinphoneSubscriptionActive + 1, liblinphone_tester_sip_timeout)); LinphoneAddress
-		   *michelle2DeviceAddr =
-		   linphone_address_clone(linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(michelle2.getLc())));
-		        michelle2Cr = linphone_core_search_chat_room(michelle2.getLc(), NULL, michelle2DeviceAddr, confAddr,
-		   NULL); linphone_address_unref(michelle2DeviceAddr); BC_ASSERT_PTR_NOT_NULL(michelle2Cr);
-		*/
-
 		msg_text = "message marie blabla";
 		msg = ClientConference::sendTextMsg(marieCr, msg_text);
 		BC_ASSERT_TRUE(CoreManagerAssert({focus, marie, pauline, michelle, michelle2, laure, berthe}).wait([msg] {
@@ -2672,7 +2645,8 @@ void create_conference_base(time_t start_time,
                             bool_t do_not_use_proxy,
                             LinphoneMediaDirection video_direction,
                             bool_t network_restart,
-                            LinphoneConferenceSecurityLevel security_level) {
+                            LinphoneConferenceSecurityLevel security_level,
+                            bool_t all_speakers) {
 	Focus focus("chloe_rc");
 	{ // to make sure focus is destroyed after clients.
 		ClientConference marie("marie_rc", focus.getIdentity());
@@ -2750,8 +2724,10 @@ void create_conference_base(time_t start_time,
 		bctbx_list_t *participants_info = NULL;
 		std::map<LinphoneCoreManager *, LinphoneParticipantInfo *> participantList;
 		participantList.insert(
-		    std::make_pair(laure.getCMgr(), add_participant_info_to_list(&participants_info, laure.getCMgr()->identity,
-		                                                                 LinphoneParticipantRoleListener, -1)));
+		    std::make_pair(laure.getCMgr(),
+		                   add_participant_info_to_list(
+		                       &participants_info, laure.getCMgr()->identity,
+		                       (all_speakers) ? LinphoneParticipantRoleSpeaker : LinphoneParticipantRoleListener, -1)));
 		participantList.insert(std::make_pair(
 		    pauline.getCMgr(), add_participant_info_to_list(&participants_info, pauline.getCMgr()->identity,
 		                                                    LinphoneParticipantRoleSpeaker, -1)));
@@ -2798,6 +2774,12 @@ void create_conference_base(time_t start_time,
 			ms_message("%s is entering conference %s", linphone_core_get_identity(mgr->lc), conference_address_str);
 			linphone_core_invite_address_with_params_2(mgr->lc, confAddr, new_params, NULL, nullptr);
 			linphone_call_params_unref(new_params);
+			LinphoneCall *pcall = linphone_core_get_call_by_remote_address2(mgr->lc, confAddr);
+			BC_ASSERT_PTR_NOT_NULL(pcall);
+			if (pcall) {
+				LinphoneCallLog *call_log = linphone_call_get_call_log(pcall);
+				BC_ASSERT_TRUE(linphone_call_log_was_conference(call_log));
+			}
 		}
 
 		int idx = 1;
@@ -3539,10 +3521,6 @@ void create_conference_base(time_t start_time,
 						bool video_available =
 						    !!linphone_participant_device_get_stream_availability(d, LinphoneStreamTypeVideo);
 						if (enable) {
-							//								if (linphone_conference_is_me(conference,
-							// linphone_participant_device_get_address(d))) {
-							// BC_ASSERT_TRUE(video_available ==
-							// video_enabled); 								} else {
 							LinphoneMediaDirection video_direction =
 							    linphone_participant_device_get_stream_capability(d, LinphoneStreamTypeVideo);
 							BC_ASSERT_TRUE(video_available == (((video_direction == LinphoneMediaDirectionSendOnly) ||
@@ -3785,8 +3763,8 @@ void create_conference_base(time_t start_time,
 			                             focus_stat3.number_of_LinphoneCallStreamsRunning + 1,
 			                             liblinphone_tester_sip_timeout));
 
-			// Laure is a listener, therefore a media capability changed is only notified if the video receive component
-			// is added
+			// Laure is a listener therefore the media capability changed notification is only received if the video
+			// receive component is added
 			if ((video_direction == LinphoneMediaDirectionSendOnly) ||
 			    (video_direction == LinphoneMediaDirectionInactive)) {
 				BC_ASSERT_TRUE(wait_for_list(coresList,
@@ -3805,6 +3783,19 @@ void create_conference_base(time_t start_time,
 				                             &laure.getStats().number_of_participant_devices_media_capability_changed,
 				                             laure_stat3.number_of_participant_devices_media_capability_changed + 1,
 				                             liblinphone_tester_sip_timeout));
+			} else {
+				BC_ASSERT_FALSE(
+				    wait_for_list(coresList, &focus.getStats().number_of_participant_devices_media_capability_changed,
+				                  focus_stat3.number_of_participant_devices_media_capability_changed + 1, 1000));
+				BC_ASSERT_FALSE(
+				    wait_for_list(coresList, &marie.getStats().number_of_participant_devices_media_capability_changed,
+				                  marie_stat3.number_of_participant_devices_media_capability_changed + 1, 1000));
+				BC_ASSERT_FALSE(
+				    wait_for_list(coresList, &pauline.getStats().number_of_participant_devices_media_capability_changed,
+				                  pauline_stat3.number_of_participant_devices_media_capability_changed + 1, 1000));
+				BC_ASSERT_FALSE(
+				    wait_for_list(coresList, &laure.getStats().number_of_participant_devices_media_capability_changed,
+				                  laure_stat3.number_of_participant_devices_media_capability_changed + 1, 1000));
 			}
 
 			for (auto mgr : conferenceMgrs) {
@@ -3822,12 +3813,18 @@ void create_conference_base(time_t start_time,
 						bctbx_list_t *devices = linphone_participant_get_devices(p);
 						for (bctbx_list_t *itd = devices; itd; itd = bctbx_list_next(itd)) {
 							LinphoneParticipantDevice *d = (LinphoneParticipantDevice *)bctbx_list_get_data(itd);
-							LinphoneMediaDirection expected_video_direction =
-							    (((video_direction == LinphoneMediaDirectionInactive) ||
-							      (video_direction == LinphoneMediaDirectionRecvOnly)) &&
-							     (layout == LinphoneConferenceLayoutGrid))
-							        ? LinphoneMediaDirectionInactive
-							        : LinphoneMediaDirectionRecvOnly;
+							LinphoneMediaDirection expected_video_direction = LinphoneMediaDirectionInactive;
+							if (all_speakers) {
+								expected_video_direction = LinphoneMediaDirectionSendRecv;
+							} else {
+								if (((video_direction == LinphoneMediaDirectionInactive) ||
+								     (video_direction == LinphoneMediaDirectionRecvOnly)) &&
+								    (layout == LinphoneConferenceLayoutGrid)) {
+									expected_video_direction = LinphoneMediaDirectionInactive;
+								} else {
+									expected_video_direction = LinphoneMediaDirectionRecvOnly;
+								}
+							}
 							BC_ASSERT_EQUAL(
 							    linphone_participant_device_get_stream_capability(d, LinphoneStreamTypeVideo),
 							    expected_video_direction, int, "%0d");
@@ -3876,7 +3873,9 @@ void create_conference_base(time_t start_time,
 				members.push_back(michelle.getCMgr());
 				participantList.insert(std::make_pair(
 				    michelle.getCMgr(), add_participant_info_to_list(&participants_info, michelle.getCMgr()->identity,
-				                                                     LinphoneParticipantRoleListener, 0)));
+				                                                     (all_speakers) ? LinphoneParticipantRoleSpeaker
+				                                                                    : LinphoneParticipantRoleListener,
+				                                                     0)));
 
 				extra_participants = 1;
 
@@ -4078,10 +4077,12 @@ void create_conference_base(time_t start_time,
 							const bool_t enabled = linphone_call_params_video_enabled(call_cparams);
 							no_streams_audio = compute_no_audio_streams(pcall, pconference);
 							no_active_streams_video = compute_no_video_streams(enabled, pcall, pconference);
-							no_streams_video = ((security_level == LinphoneConferenceSecurityLevelEndToEnd) &&
-							                    (layout == LinphoneConferenceLayoutActiveSpeaker))
-							                       ? 6
-							                       : 4;
+							no_streams_video = (all_speakers)
+							                       ? no_active_streams_video
+							                       : (((security_level == LinphoneConferenceSecurityLevelEndToEnd) &&
+							                           (layout == LinphoneConferenceLayoutActiveSpeaker))
+							                              ? 6
+							                              : 4);
 
 							_linphone_call_check_max_nb_streams(pcall, no_streams_audio, no_streams_video,
 							                                    no_streams_text);
@@ -4266,33 +4267,6 @@ void create_conference_base(time_t start_time,
 						BC_ASSERT_TRUE(wait_for_list(coresList, &berthe.getStats().number_of_LinphoneCallStreamsRunning,
 						                             3, liblinphone_tester_sip_timeout));
 					}
-
-					/*
-					//					if ((audio_only_participant == FALSE) && ((video_direction !=
-					// LinphoneMediaDirectionRecvOnly) || (layout
-					// == LinphoneConferenceLayoutActiveSpeaker))) {
-					if ((video_direction != LinphoneMediaDirectionRecvOnly) ||
-					    (layout == LinphoneConferenceLayoutActiveSpeaker)) {
-					    BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneCallUpdating,
-					                                 pauline_stat2.number_of_LinphoneCallUpdating + 1,
-					                                 liblinphone_tester_sip_timeout));
-					    BC_ASSERT_TRUE(wait_for_list(
-					        coresList, &pauline.getStats().number_of_LinphoneCallStreamsRunning,
-					        pauline_stat2.number_of_LinphoneCallStreamsRunning + 1, liblinphone_tester_sip_timeout));
-					    BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneCallUpdating,
-					                                 marie_stat2.number_of_LinphoneCallUpdating + 1,
-					                                 liblinphone_tester_sip_timeout));
-					    BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneCallStreamsRunning,
-					                                 marie_stat2.number_of_LinphoneCallStreamsRunning + 1,
-					                                 liblinphone_tester_sip_timeout));
-					    BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_LinphoneCallUpdating,
-					                                 michelle_stat2.number_of_LinphoneCallUpdating + 1,
-					                                 liblinphone_tester_sip_timeout));
-					    BC_ASSERT_TRUE(wait_for_list(
-					        coresList, &michelle.getStats().number_of_LinphoneCallStreamsRunning,
-					        michelle_stat2.number_of_LinphoneCallStreamsRunning + 1, liblinphone_tester_sip_timeout));
-					}
-					*/
 					BC_ASSERT_TRUE(wait_for_list(
 					    coresList, &focus.getStats().number_of_LinphoneCallUpdatedByRemote,
 					    focus_stat2.number_of_LinphoneCallUpdatedByRemote + (audio_only_participant) ? 3 : 4,
@@ -5282,7 +5256,7 @@ void create_conference_with_late_participant_addition_base(time_t start_time,
 		int participant_added = ((one_addition) ? 1 : 2);
 
 		LinphoneParticipantInfo *berthe_participant_info = add_participant_info_to_list(
-		    &participants_info, berthe.getCMgr()->identity, LinphoneParticipantRoleListener, -1);
+		    &participants_info, berthe.getCMgr()->identity, LinphoneParticipantRoleSpeaker, -1);
 		if (accept) {
 			if (berthe_call) {
 				linphone_call_accept(berthe_call);
@@ -5321,7 +5295,7 @@ void create_conference_with_late_participant_addition_base(time_t start_time,
 				conferenceMgrs.push_back(michelle.getCMgr());
 				members.push_back(michelle.getCMgr());
 				LinphoneParticipantInfo *participant_info = add_participant_info_to_list(
-				    &participants_info, michelle.getCMgr()->identity, LinphoneParticipantRoleListener, -1);
+				    &participants_info, michelle.getCMgr()->identity, LinphoneParticipantRoleSpeaker, -1);
 				participantList.insert(std::make_pair(michelle.getCMgr(), participant_info));
 				memberList.insert(std::make_pair(michelle.getCMgr(), participant_info));
 
@@ -5482,10 +5456,6 @@ void create_conference_with_late_participant_addition_base(time_t start_time,
 					bool video_available =
 					    !!linphone_participant_device_get_stream_availability(d, LinphoneStreamTypeVideo);
 					if (enable) {
-						//								if (linphone_conference_is_me(conference,
-						// linphone_participant_device_get_address(d))) {
-						// BC_ASSERT_TRUE(video_available ==
-						// video_enabled); 								} else {
 						LinphoneMediaDirection video_direction =
 						    linphone_participant_device_get_stream_capability(d, LinphoneStreamTypeVideo);
 						BC_ASSERT_TRUE(video_available == (((video_direction == LinphoneMediaDirectionSendOnly) ||
@@ -8021,8 +7991,6 @@ void create_simple_conference_merging_calls_base(bool_t enable_ice,
 				if (participant_call) {
 					BC_ASSERT_PTR_NOT_NULL(linphone_call_get_conference(participant_call));
 					BC_ASSERT_FALSE(linphone_call_is_in_conference(participant_call));
-					// BC_ASSERT_TRUE(linphone_call_get_microphone_muted(participant_call)
-					// == (mgr == pauline.getCMgr()));
 					_linphone_call_check_nb_active_streams(participant_call, 1, (toggle_video) ? 4 : 0, 0);
 				}
 			}
@@ -8043,18 +8011,11 @@ void create_simple_conference_merging_calls_base(bool_t enable_ice,
 		}
 
 		stats focus_stat = focus.getStats();
-		stats pauline_stat = pauline.getStats();
-		stats laure_stat = laure.getStats();
 		const char *newSubject = "Let's go drink a beer";
 		linphone_conference_set_subject(conf, newSubject);
 
 		BC_ASSERT_TRUE(wait_for_list(coresList, &focus.getStats().number_of_subject_changed,
 		                             focus_stat.number_of_subject_changed + 1, liblinphone_tester_sip_timeout));
-		BC_ASSERT_TRUE(wait_for_list(coresList, &pauline.getStats().number_of_subject_changed,
-		                             pauline_stat.number_of_subject_changed + 1, liblinphone_tester_sip_timeout));
-		BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_subject_changed,
-		                             laure_stat.number_of_subject_changed + 1, liblinphone_tester_sip_timeout));
-
 		for (auto mgr : {marie.getCMgr(), pauline.getCMgr(), laure.getCMgr()}) {
 			auto old_stats = participant_stats.front();
 			BC_ASSERT_TRUE(wait_for_list(coresList, &mgr->stat.number_of_subject_changed,
@@ -8085,8 +8046,8 @@ void create_simple_conference_merging_calls_base(bool_t enable_ice,
 		}
 
 		focus_stat = focus.getStats();
-		pauline_stat = pauline.getStats();
 		stats marie_stat = marie.getStats();
+		stats pauline_stat = pauline.getStats();
 
 		// Laure's core suddenly stops
 		ms_message("%s core suddently loses network and restarts", linphone_core_get_identity(laure.getLc()));
diff --git a/tester/local_conference_tester_functions.h b/tester/local_conference_tester_functions.h
index fd01e888a057d6e798e07d0ce762597e2e3bb250..ff660bf560f7f011aaa1219f1b47eab9a56a4d44 100644
--- a/tester/local_conference_tester_functions.h
+++ b/tester/local_conference_tester_functions.h
@@ -380,7 +380,8 @@ void create_conference_base(time_t start_time,
                             bool_t do_not_use_proxy,
                             LinphoneMediaDirection video_direction,
                             bool_t network_restart,
-                            LinphoneConferenceSecurityLevel security_level);
+                            LinphoneConferenceSecurityLevel security_level,
+                            bool_t all_speakers);
 
 void wait_for_conference_streams(std::initializer_list<std::reference_wrapper<CoreManager>> coreMgrs,
                                  std::list<LinphoneCoreManager *> conferenceMgrs,
diff --git a/tester/local_ice_conference_tester.cpp b/tester/local_ice_conference_tester.cpp
index 4e4f63925bf7297ac98092d3a6656bb10fd353f0..b87731d202996320e462a8e92e0f2b8858611d26 100644
--- a/tester/local_ice_conference_tester.cpp
+++ b/tester/local_ice_conference_tester.cpp
@@ -27,64 +27,71 @@ namespace LinphoneTest {
 static void create_simple_ice_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, TRUE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_stun_ice_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, TRUE, TRUE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_ice_srtp_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionSRTP, TRUE, LinphoneConferenceLayoutGrid, TRUE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_ice_dtls_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionDTLS, TRUE, LinphoneConferenceLayoutGrid, TRUE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_stun_ice_srtp_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionSRTP, TRUE, LinphoneConferenceLayoutActiveSpeaker, TRUE, TRUE, FALSE,
 	                       FALSE, FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE,
-	                       LinphoneConferenceSecurityLevelNone);
+	                       LinphoneConferenceSecurityLevelNone, FALSE);
 }
 
 static void create_simple_ice_conference_with_audio_only_participant(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, TRUE, TRUE, TRUE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_stun_ice_conference_with_audio_only_participant(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, TRUE, TRUE, TRUE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_stun_ice_srtp_conference_with_audio_only_participant(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionSRTP, TRUE, LinphoneConferenceLayoutGrid, TRUE, TRUE, TRUE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_point_to_point_encrypted_ice_conference(void) {
 	create_conference_base(ms_time(NULL), -1, TRUE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, TRUE, FALSE, FALSE, FALSE,
 	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE,
-	                       LinphoneConferenceSecurityLevelPointToPoint);
+	                       LinphoneConferenceSecurityLevelPointToPoint, FALSE);
 }
 
 static void create_simple_end_to_end_encrypted_ice_conference(void) {
 	create_conference_base(ms_time(NULL), -1, TRUE, LinphoneConferenceParticipantListTypeOpen, TRUE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, TRUE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE,
-	                       LinphoneConferenceSecurityLevelEndToEnd);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelEndToEnd,
+	                       FALSE);
 }
 
 static void create_simple_ice_conference_merging_calls(void) {
diff --git a/tester/local_scheduled_conference_tester.cpp b/tester/local_scheduled_conference_tester.cpp
index f5809aec54bf31e20fd76e3e84cef9976a818814..bd933b74e0230278b71ba23826dd984ca8c06a6f 100644
--- a/tester/local_scheduled_conference_tester.cpp
+++ b/tester/local_scheduled_conference_tester.cpp
@@ -163,97 +163,113 @@ static void create_conference_on_unresponsive_server(void) {
 static void create_simple_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_point_to_point_encrypted_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
 	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE,
-	                       LinphoneConferenceSecurityLevelPointToPoint);
+	                       LinphoneConferenceSecurityLevelPointToPoint, FALSE);
 }
 
 static void create_simple_end_to_end_encrypted_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE,
-	                       LinphoneConferenceSecurityLevelEndToEnd);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelEndToEnd,
+	                       FALSE);
 }
 
 static void create_simple_conference_with_server_restart(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, TRUE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_conference_with_client_restart(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
-	                       TRUE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone);
+	                       TRUE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_zrtp_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionZRTP, TRUE, LinphoneConferenceLayoutActiveSpeaker, FALSE, FALSE,
 	                       FALSE, FALSE, FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE,
-	                       LinphoneConferenceSecurityLevelNone);
+	                       LinphoneConferenceSecurityLevelNone, FALSE);
 }
 
 static void create_simple_dtls_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionDTLS, TRUE, LinphoneConferenceLayoutActiveSpeaker, FALSE, FALSE,
 	                       FALSE, FALSE, FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE,
-	                       LinphoneConferenceSecurityLevelNone);
+	                       LinphoneConferenceSecurityLevelNone, FALSE);
 }
 
 static void create_simple_srtp_conference(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionSRTP, TRUE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
+}
+
+static void create_conference_with_all_speakers_and_uninvited_participant(void) {
+	create_conference_base(ms_time(NULL), -1, TRUE, LinphoneConferenceParticipantListTypeOpen, FALSE,
+	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutActiveSpeaker, FALSE, FALSE,
+	                       FALSE, FALSE, FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE,
+	                       LinphoneConferenceSecurityLevelNone, TRUE);
 }
 
-static void create_conference_with_uninvited_participant(void) {
+static void create_conference_with_listeners_and_uninvited_participant(void) {
 	create_conference_base(ms_time(NULL), -1, TRUE, LinphoneConferenceParticipantListTypeOpen, TRUE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, TRUE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_conference_with_uninvited_participant_not_allowed(void) {
 	create_conference_base(ms_time(NULL), -1, TRUE, LinphoneConferenceParticipantListTypeClosed, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutActiveSpeaker, FALSE, FALSE,
 	                       FALSE, FALSE, FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE,
-	                       LinphoneConferenceSecurityLevelNone);
+	                       LinphoneConferenceSecurityLevelNone, FALSE);
 }
 
 static void create_conference_starting_immediately(void) {
 	create_conference_base(ms_time(NULL), 0, FALSE, LinphoneConferenceParticipantListTypeClosed, FALSE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutGrid, FALSE, FALSE, FALSE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionRecvOnly, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_conference_starting_in_the_past(void) {
 	create_conference_base(ms_time(NULL) - 600, 900, FALSE, LinphoneConferenceParticipantListTypeClosed, TRUE,
 	                       LinphoneMediaEncryptionNone, FALSE, LinphoneConferenceLayoutActiveSpeaker, FALSE, FALSE,
 	                       FALSE, FALSE, FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE,
-	                       LinphoneConferenceSecurityLevelNone);
+	                       LinphoneConferenceSecurityLevelNone, FALSE);
 }
 
 static void create_simple_conference_with_audio_only_participant(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, FALSE, FALSE, TRUE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_conference_with_audio_only_and_uninvited_participant(void) {
 	create_conference_base(ms_time(NULL), -1, TRUE, LinphoneConferenceParticipantListTypeOpen, TRUE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, FALSE, FALSE, TRUE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_simple_conference_with_audio_only_participant_enabling_video(void) {
 	create_conference_base(ms_time(NULL), -1, FALSE, LinphoneConferenceParticipantListTypeOpen, FALSE,
 	                       LinphoneMediaEncryptionNone, TRUE, LinphoneConferenceLayoutGrid, FALSE, FALSE, TRUE, FALSE,
-	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone);
+	                       FALSE, FALSE, LinphoneMediaDirectionSendRecv, FALSE, LinphoneConferenceSecurityLevelNone,
+	                       FALSE);
 }
 
 static void create_conference_with_late_participant_addition(void) {
@@ -2395,8 +2411,10 @@ static test_t local_conference_scheduled_conference_basic_tests[] = {
     TEST_NO_TAG("Call to inexisting conference address", LinphoneTest::call_to_inexisting_conference_address),
     TEST_NO_TAG("Create conference on unresponsive server", LinphoneTest::create_conference_on_unresponsive_server),
     TEST_NO_TAG("Create simple conference", LinphoneTest::create_simple_conference),
-    TEST_NO_TAG("Create conference with uninvited participant",
-                LinphoneTest::create_conference_with_uninvited_participant),
+    TEST_NO_TAG("Create conference with listeners and uninvited participant",
+                LinphoneTest::create_conference_with_listeners_and_uninvited_participant),
+    TEST_NO_TAG("Create conference with all speakers and uninvited participant",
+                LinphoneTest::create_conference_with_all_speakers_and_uninvited_participant),
     TEST_NO_TAG("Create simple conference with server restart",
                 LinphoneTest::create_simple_conference_with_server_restart),
     TEST_NO_TAG("Create simple conference with client restart",