diff --git a/Linphone/core/CMakeLists.txt b/Linphone/core/CMakeLists.txt index 48bba6ffc..a3e4c34f4 100644 --- a/Linphone/core/CMakeLists.txt +++ b/Linphone/core/CMakeLists.txt @@ -18,7 +18,6 @@ list(APPEND _LINPHONEAPP_SOURCES core/call-history/CallHistoryProxy.cpp core/camera/CameraGui.cpp core/camera/CameraDummy.cpp - core/camera/PreviewManager.cpp core/chat/ChatCore.cpp core/chat/ChatGui.cpp core/chat/ChatList.cpp diff --git a/Linphone/core/camera/CameraGui.cpp b/Linphone/core/camera/CameraGui.cpp index d1b826949..61ac6a257 100644 --- a/Linphone/core/camera/CameraGui.cpp +++ b/Linphone/core/camera/CameraGui.cpp @@ -25,7 +25,6 @@ #include "CameraDummy.hpp" #include "CameraGui.hpp" -#include "PreviewManager.hpp" #include "core/App.hpp" #include "core/call/CallCore.hpp" #include "core/call/CallGui.hpp" @@ -51,6 +50,10 @@ CameraGui::CameraGui(QQuickItem *parent) : QQuickFramebufferObject(parent) { CameraGui::~CameraGui() { mustBeInMainThread("~" + getClassName()); mRefreshTimer.stop(); + if(mIsPreview) { + lDebug() << "[CameraGui] Deactivation"; + CoreModel::getInstance()->getCore()->enableVideoPreview(false); + } setWindowIdLocation(None); } @@ -77,6 +80,7 @@ void CameraGui::clearRenderer() { mLastRenderer = nullptr; } + QQuickFramebufferObject::Renderer *CameraGui::createRenderer() const { QQuickFramebufferObject::Renderer *renderer = NULL; lDebug() << log().arg("CreateRenderer"); @@ -84,9 +88,11 @@ QQuickFramebufferObject::Renderer *CameraGui::createRenderer() const { // A renderer is mandatory, we cannot wait async. switch (getSourceLocation()) { case CorePreview: { - // if (resetWindowId) PreviewManager::getInstance()->unsubscribe(this); - renderer = PreviewManager::getInstance()->subscribe(this); - //(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId(); + App::postModelBlock([qmlName = mQmlName, callGui = mCallGui, &renderer]() { + lInfo() << "[Camera] (" << qmlName << ") Camera create from Preview"; + renderer = (QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId( + nullptr); + }); } break; case Call: { @@ -135,7 +141,10 @@ void CameraGui::updateSDKRenderer(QQuickFramebufferObject::Renderer *renderer) { lDebug() << log().arg("Apply Qt Renderer to SDK") << renderer; switch (getSourceLocation()) { case CorePreview: { - + App::postModelBlock([qmlName = mQmlName, renderer]() { + lInfo() << "[Camera] (" << qmlName << ") Camera to CorePreview"; + CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer); + }); } break; case Call: { App::postModelAsync([qmlName = mQmlName, callGui = mCallGui, renderer]() { @@ -197,6 +206,11 @@ bool CameraGui::getIsPreview() const { void CameraGui::setIsPreview(bool status) { if (mIsPreview != status) { mIsPreview = status; + // We block it to serialize the action and allow only one CameraGui to change the state. + App::postModelBlock([status]() { + lDebug() << "[CameraGui] " << (status ? "Activation" : "Deactivation"); + CoreModel::getInstance()->getCore()->enableVideoPreview(status); + }); updateWindowIdLocation(); update(); @@ -240,18 +254,9 @@ CameraGui::WindowIdLocation CameraGui::getSourceLocation() const { void CameraGui::setWindowIdLocation(const WindowIdLocation &location) { if (mWindowIdLocation != location) { lDebug() << log().arg("Update Window Id location from %2 to %3").arg(mWindowIdLocation).arg(location); - if (mWindowIdLocation == CorePreview) PreviewManager::getInstance()->unsubscribe(this); - // else if (mWindowIdLocation != None) resetWindowId(); // Location change: Reset old window ID. resetWindowId(); mWindowIdLocation = location; - if (mWindowIdLocation == CorePreview) PreviewManager::getInstance()->subscribe(this); - else updateSDKRenderer(); - // QTimer::singleShot(100, this, &CameraGui::requestNewRenderer); - // if (mWindowIdLocation == WindowIdLocation::CorePreview) { - // mLastVideoDefinition = - // CoreManager::getInstance()->getSettingsModel()->getCurrentPreviewVideoDefinition(); emit - // videoDefinitionChanged(); mLastVideoDefinitionChecker.start(); - // } else mLastVideoDefinitionChecker.stop(); + updateSDKRenderer(); } } void CameraGui::updateWindowIdLocation() { @@ -262,7 +267,7 @@ void CameraGui::updateWindowIdLocation() { setWindowIdLocation(WindowIdLocation::Device); else setWindowIdLocation(WindowIdLocation::CorePreview); } - +// TODO to remove void CameraGui::callStateChanged(LinphoneEnums::CallState state) { if (getSourceLocation() == CorePreview && state == LinphoneEnums::CallState::Connected) { if (!getIsReady()) { diff --git a/Linphone/core/camera/PreviewManager.cpp b/Linphone/core/camera/PreviewManager.cpp deleted file mode 100644 index 8804635df..000000000 --- a/Linphone/core/camera/PreviewManager.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2010-2024 Belledonne Communications SARL. - * - * This file is part of linphone-desktop - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#include "../App.hpp" -#include "PreviewManager.hpp" -#include "tool/Utils.hpp" - -DEFINE_ABSTRACT_OBJECT(PreviewManager) - -// ============================================================================= -PreviewManager *PreviewManager::gInstance = nullptr; - -PreviewManager::PreviewManager(QObject *parent) : QObject(parent) { -} - -PreviewManager::~PreviewManager() { -} - -PreviewManager *PreviewManager::getInstance() { - if (gInstance) return gInstance; - else { - gInstance = new PreviewManager(); - return gInstance; - } -} - -// Create a Renderer from SDK preview -QQuickFramebufferObject::Renderer *PreviewManager::subscribe(const CameraGui *candidate) { - QQuickFramebufferObject::Renderer *renderer = nullptr; - mCounterMutex.lock(); - - if (mCandidates.size() == 0) { - activate(); - } - auto itCandidate = - std::find_if(mCandidates.begin(), mCandidates.end(), - [candidate](const QPair &item) { - return item.first == candidate; - }); - if (itCandidate == mCandidates.end()) { - connect(candidate, &QObject::destroyed, this, qOverload(&PreviewManager::unsubscribe)); - mCandidates.append({candidate, nullptr}); - itCandidate = mCandidates.end() - 1; - lDebug() << log().arg("Subscribing New") << itCandidate->first->getQmlName(); - } else { - lDebug() << log().arg("Resubscribing") << itCandidate->first->getQmlName(); - } - mCounterMutex.unlock(); - App::postModelBlock([&renderer, isFirst = (itCandidate == mCandidates.begin()), - name = itCandidate->first->getQmlName()]() { - renderer = - (QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId( - nullptr); - if (!renderer) { // TODO debug - renderer = - (QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId( - nullptr); - } - if (isFirst) { - lDebug() << "[PreviewManager] " << name << " Set Native Preview Id with " << renderer; - CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer); - } - }); - mCounterMutex.lock(); - itCandidate->second = renderer; - mCounterMutex.unlock(); - return renderer; -} - -void PreviewManager::unsubscribe(const CameraGui *candidate) { // If nullptr, Use of sender() - mCounterMutex.lock(); - auto itCandidate = std::find_if(mCandidates.begin(), mCandidates.end(), - [candidate = (candidate ? candidate : sender())]( - const QPair &item) { - return item.first == candidate; - }); - if (itCandidate != mCandidates.end()) { - lDebug() << log().arg("Unsubscribing") << itCandidate->first->getQmlName(); - disconnect(candidate, nullptr, this, nullptr); - if (mCandidates.size() == 1) { - mCandidates.erase(itCandidate); - deactivate(); - } else if (mCandidates.begin() == itCandidate) { - mCandidates.erase(itCandidate); - lDebug() << log().arg("Update") << mCandidates.first().first->getQmlName(); - auto renderer = mCandidates.first().second; - if (renderer) - App::postModelBlock([renderer = mCandidates.first().second]() { - CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer); - }); - } else { - mCandidates.erase(itCandidate); - } - } - mCounterMutex.unlock(); -} - -void PreviewManager::unsubscribe(QObject *sender) { - unsubscribe(dynamic_cast(sender)); -} - -void PreviewManager::activate() { - App::postModelAsync([]() { - lDebug() << "[PreviewManager] Activation"; - CoreModel::getInstance()->getCore()->enableVideoPreview(true); - }); -} - -void PreviewManager::deactivate() { - App::postModelAsync([]() { - lDebug() << "[PreviewManager] Deactivation"; - CoreModel::getInstance()->getCore()->enableVideoPreview(false); - }); -} diff --git a/Linphone/core/camera/PreviewManager.hpp b/Linphone/core/camera/PreviewManager.hpp deleted file mode 100644 index f30749fa9..000000000 --- a/Linphone/core/camera/PreviewManager.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2024 Belledonne Communications SARL. - * - * This file is part of linphone-desktop - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef PREVIEW_MANAGER_H_ -#define PREVIEW_MANAGER_H_ - -#include "CameraGui.hpp" -#include "tool/AbstractObject.hpp" -#include -#include -#include -#include - -// Manage the SDK preview as a singleton. -// The goal is to process the limitation that only one preview can be displayed. -// On asynchronized application, the destruction of a previous Preview can be done AFTER the creation on a new Preview -// Sticker. - -// ============================================================================= - -class PreviewManager : public QObject, public AbstractObject { - Q_OBJECT -public: - PreviewManager(QObject *parent = nullptr); - virtual ~PreviewManager(); - - static PreviewManager *getInstance(); - - QQuickFramebufferObject::Renderer *subscribe(const CameraGui *candidate); - void unsubscribe(const CameraGui *candidate); - - void activate(); - void deactivate(); -public slots: - void unsubscribe(QObject *sender); - -private: - QMutex mCounterMutex; - QList> mCandidates; - static PreviewManager *gInstance; - QQuickFramebufferObject::Renderer *mPreviewRenderer = nullptr; - DECLARE_ABSTRACT_OBJECT -}; - -#endif diff --git a/external/linphone-sdk b/external/linphone-sdk index f77616e23..323a97327 160000 --- a/external/linphone-sdk +++ b/external/linphone-sdk @@ -1 +1 @@ -Subproject commit f77616e23b2d69c0d17a49044a081cd1b8ec5ce1 +Subproject commit 323a973275fdb2d99da91c04b1c74816f92b11d3