diff --git a/src/avadapter.cpp b/src/avadapter.cpp index 9ba43dd7e1be18d601682880c7a7857d6f90ef19..541216c3304d400cfce8914121d61d393f0ecba8 100644 --- a/src/avadapter.cpp +++ b/src/avadapter.cpp @@ -36,18 +36,15 @@ AvAdapter::AvAdapter(LRCInstance* instance, QObject* parent) : QmlAdapterBase(instance, parent) { - connect(lrcInstance_->renderer(), &RenderManager::previewFrameStarted, [this]() { - // TODO: listen to the correct signals that are needed to be added in daemon or lrc - auto callId = lrcInstance_->getCurrentCallId(); - if (!callId.isEmpty()) - set_currentRenderingDeviceType( - lrcInstance_->avModel().getCurrentRenderedDevice(callId).type); - }); - connect(&lrcInstance_->avModel(), &lrc::api::AVModel::audioDeviceEvent, this, &AvAdapter::onAudioDeviceEvent); + connect(&lrcInstance_->avModel(), &lrc::api::AVModel::rendererStarted, [this](const QString&) { + auto callId = lrcInstance_->getCurrentCallId(); + set_currentRenderingDeviceType( + lrcInstance_->getCurrentCallModel()->getCurrentRenderedDevice(callId).type); + }); } // The top left corner of primary screen is (0, 0). @@ -327,23 +324,3 @@ AvAdapter::setHardwareAcceleration(bool accelerate) { lrcInstance_->avModel().setHardwareAcceleration(accelerate); } - -void -AvAdapter::startPreviewing(bool force) -{ - lrcInstance_->renderer()->startPreviewing(force); -} - -void -AvAdapter::stopPreviewing() -{ - if (!lrcInstance_->hasActiveCall(true)) { - lrcInstance_->renderer()->stopPreviewing(); - } -} - -bool -AvAdapter::isPreviewing() -{ - return lrcInstance_->renderer()->isPreviewing(); -} \ No newline at end of file diff --git a/src/avadapter.h b/src/avadapter.h index b4e62341179f17d7337100c386b2c5c4ace23d90..68e3a893d26ad977bb348ed3ac8ba5611131f6c7 100644 --- a/src/avadapter.h +++ b/src/avadapter.h @@ -77,9 +77,6 @@ protected: // TODO: to be removed Q_INVOKABLE bool getHardwareAcceleration(); Q_INVOKABLE void setHardwareAcceleration(bool accelerate); - Q_INVOKABLE bool isPreviewing(); - Q_INVOKABLE void startPreviewing(bool force = false); - Q_INVOKABLE void stopPreviewing(); private Q_SLOTS: void onAudioDeviceEvent(); diff --git a/src/calladapter.cpp b/src/calladapter.cpp index 0ba242ec78b8ed3617a2994802ef5c292e276530..153b7b40da6a3dca150d586e668163287445c2f6 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -654,6 +654,17 @@ CallAdapter::updateCallOverlay(const lrc::api::conversation::Info& convInfo) bool isConferenceCall = !convInfo.confId.isEmpty() || (convInfo.confId.isEmpty() && call->participantsInfos.size() != 0); bool isGrid = call->layout == lrc::api::call::Layout::GRID; + QString previewId {}; + if (!isAudioOnly && !isVideoMuted && call->status == lrc::api::call::Status::IN_PROGRESS) { + for (const auto& media : call->mediaList) { + if (media["MEDIA_TYPE"] == "MEDIA_TYPE_VIDEO") { + if (media["ENABLED"] == "true" && media["MUTED"] == "false") { + previewId = media["SOURCE"]; + break; + } + } + } + } Q_EMIT updateOverlay(isPaused, isAudioOnly, @@ -661,7 +672,8 @@ CallAdapter::updateCallOverlay(const lrc::api::conversation::Info& convInfo) isVideoMuted, accInfo.profileInfo.type == lrc::api::profile::Type::SIP, isConferenceCall, - isGrid); + isGrid, + previewId); } void diff --git a/src/calladapter.h b/src/calladapter.h index e9f39ba9cf5c915d5635f7457772bd097e1f68c6..e7ba606a88e7c7658a538bff6a215eba9b79f85a 100644 --- a/src/calladapter.h +++ b/src/calladapter.h @@ -101,7 +101,8 @@ Q_SIGNALS: bool isVideoMuted, bool isSIP, bool isConferenceCall, - bool isGrid); + bool isGrid, + const QString& previewId); void remoteRecordingChanged(const QStringList& peers, bool state); void eraseRemoteRecording(); diff --git a/src/commoncomponents/PhotoboothView.qml b/src/commoncomponents/PhotoboothView.qml index 80faca19f95d216cb0d4888922991ca4258cedbe..bee3ea5cc6a7479ef723ad0860cc50c727e74ab3 100644 --- a/src/commoncomponents/PhotoboothView.qml +++ b/src/commoncomponents/PhotoboothView.qml @@ -39,13 +39,14 @@ Item { height: boothLayout.height function startBooth() { - AvAdapter.startPreviewing(false) + preview.deviceId = VideoDevices.getDefaultDevice() + preview.rendererId = VideoDevices.startDevice(preview.deviceId) isPreviewing = true } function stopBooth(){ if (!AccountAdapter.hasVideoCall()) { - AvAdapter.stopPreviewing() + VideoDevices.stopDevice(preview.deviceId) } isPreviewing = false } @@ -135,6 +136,9 @@ Item { anchors.fill: parent anchors.margins: 1 + property string deviceId: VideoDevices.getDefaultDevice() + rendererId: "" + visible: isPreviewing lrcInstance: LRCInstance diff --git a/src/distantrenderer.cpp b/src/distantrenderer.cpp index 8e9e4c250001fde056102a4aeb4f68429bc5ebdc..78f04862b16fbb6ddcdea6844305ac52e28c9251 100644 --- a/src/distantrenderer.cpp +++ b/src/distantrenderer.cpp @@ -34,14 +34,14 @@ DistantRenderer::DistantRenderer(QQuickItem* parent) connect(lrcInstance_->renderer(), &RenderManager::distantFrameUpdated, [this](const QString& id) { - if (distantRenderId_ == id) + if (rendererId_ == id) update(QRect(0, 0, width(), height())); }); connect(lrcInstance_->renderer(), &RenderManager::distantRenderingStopped, [this](const QString& id) { - if (distantRenderId_ == id) + if (rendererId_ == id) update(QRect(0, 0, width(), height())); }); } @@ -53,7 +53,7 @@ DistantRenderer::~DistantRenderer() {} void DistantRenderer::setRendererId(const QString& id) { - distantRenderId_ = id; + rendererId_ = id; // Note: Force a paint to update frame as we change the renderer update(QRect(0, 0, width(), height())); } @@ -61,7 +61,16 @@ DistantRenderer::setRendererId(const QString& id) QString DistantRenderer::rendererId() { - return distantRenderId_; + return rendererId_; +} + +QString +DistantRenderer::takePhoto(int size) +{ + if (auto previewImage = lrcInstance_->renderer()->getPreviewFrame(rendererId_)) { + return Utils::byteArrayToBase64String(Utils::QImageToByteArray(previewImage->copy())); + } + return {}; } int @@ -91,7 +100,7 @@ DistantRenderer::getScaledHeight() const void DistantRenderer::paint(QPainter* painter) { - lrcInstance_->renderer()->drawFrame(distantRenderId_, [this, painter](QImage* distantImage) { + lrcInstance_->renderer()->drawFrame(rendererId_, [this, painter](QImage* distantImage) { if (distantImage) { painter->setRenderHint(QPainter::Antialiasing); painter->setRenderHint(QPainter::SmoothPixmapTransform); diff --git a/src/distantrenderer.h b/src/distantrenderer.h index fef749b3e47925cc6a014cc81a1a2edcd779ba5a..ee81afa1bf0237e5143a6e208abb4cb2d57061a7 100644 --- a/src/distantrenderer.h +++ b/src/distantrenderer.h @@ -43,6 +43,7 @@ public: Q_INVOKABLE int getYOffset() const; Q_INVOKABLE double getScaledWidth() const; Q_INVOKABLE double getScaledHeight() const; + Q_INVOKABLE QString takePhoto(int size); Q_SIGNALS: void offsetChanged(); @@ -58,7 +59,7 @@ private: /* * Unique DistantRenderId for each call. */ - QString distantRenderId_; + QString rendererId_; int xOffset_ {0}; int yOffset_ {0}; double scaledWidth_ {0}; diff --git a/src/mainview/components/OngoingCallPage.qml b/src/mainview/components/OngoingCallPage.qml index e3664b2992cc96b7a60e00663feca686063f09b0..76b448747656fccddd684bb06f9652a12d18aeb6 100644 --- a/src/mainview/components/OngoingCallPage.qml +++ b/src/mainview/components/OngoingCallPage.qml @@ -42,6 +42,15 @@ Rectangle { property bool isAudioOnly: false property alias callId: distantRenderer.rendererId property var linkedWebview: null + property string callPreviewId: "" + + onCallPreviewIdChanged: { + testLog("\n\n CHANGING CALLPREVIEWID" + root.callPreviewId + " " + previewRenderer.rendererId + " \n\n") + } + + function testLog(txt) { + console.log(this, txt) + } color: "black" @@ -182,6 +191,14 @@ Rectangle { visible: !callOverlay.isAudioOnly && !callOverlay.isConferenceCall && !callOverlay.isVideoMuted && !callOverlay.isPaused && ((VideoDevices.listSize !== 0 && AvAdapter.currentRenderingDeviceType === Video.DeviceType.CAMERA) || AvAdapter.currentRenderingDeviceType !== Video.DeviceType.CAMERA ) + rendererId: root.callPreviewId + + onVisibleChanged: { + if (!visible) { + VideoDevices.stopDevice(rendererId, true) + } + } + width: Math.max(callPageMainRect.width / 5, JamiTheme.minimumPreviewWidth) x: callPageMainRect.width - previewRenderer.width - previewMargin y: previewMarginYTop @@ -274,6 +291,14 @@ Rectangle { function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isSIP, isConferenceCall, isGrid, previewId) { + if (previewId != "") { + if (root.callPreviewId != previewId) + VideoDevices.stopDevice(root.callPreviewId, true) + VideoDevices.startDevice(previewId) + } else { + VideoDevices.stopDevice(root.callPreviewId, true) + } + root.callPreviewId = previewId callOverlay.showOnHoldImage(isPaused) root.isAudioOnly = isAudioOnly audioCallPageRectCentralRect.visible = !isPaused && root.isAudioOnly diff --git a/src/mainview/components/RecordBox.qml b/src/mainview/components/RecordBox.qml index 9db8100b90d5065dcadf77b21efcac792f23a436..452e1ce876bce002e18355fad8e162890a1c73fa 100644 --- a/src/mainview/components/RecordBox.qml +++ b/src/mainview/components/RecordBox.qml @@ -59,7 +59,8 @@ Rectangle { updateState(RecordBox.States.INIT) if (isVideo) { - AvAdapter.startPreviewing(false) + previewWidget.deviceId = VideoDevices.getDefaultDevice() + previewWidget.rendererId = VideoDevices.startDevice(previewWidget.deviceId) previewAvailable = true } } @@ -79,8 +80,8 @@ Rectangle { } function closeRecorder() { - if (isVideo && AvAdapter.isPreviewing()) { - AvAdapter.stopPreviewing() + if (isVideo) { + VideoDevices.stopDevice(previewWidget.deviceId) } stopRecording() visible = false @@ -104,7 +105,7 @@ Rectangle { function startRecording() { timer.start() - pathRecorder = AVModel.startLocalRecorder(!isVideo) + pathRecorder = AVModel.startLocalMediaRecorder(VideoDevices.getDefaultDevice()) if (pathRecorder == "") { timer.stop() } @@ -251,6 +252,8 @@ Rectangle { anchors.fill: rectBox anchors.centerIn: rectBox + property string deviceId: VideoDevices.getDefaultDevice() + rendererId: VideoDevices.getDefaultDevice() lrcInstance: LRCInstance diff --git a/src/previewrenderer.cpp b/src/previewrenderer.cpp index 4faad9fa77a338559cc076a4d10ca63e1779cdb0..34452a1dd470f401978c97a02fb9358f31a74c25 100644 --- a/src/previewrenderer.cpp +++ b/src/previewrenderer.cpp @@ -19,8 +19,6 @@ #include "previewrenderer.h" -#include "lrcinstance.h" - PreviewRenderer::PreviewRenderer(QQuickItem* parent) : QQuickPaintedItem(parent) { @@ -32,9 +30,9 @@ PreviewRenderer::PreviewRenderer(QQuickItem* parent) connect(this, &PreviewRenderer::lrcInstanceChanged, [this] { if (lrcInstance_) previewFrameUpdatedConnection_ = connect(lrcInstance_->renderer(), - &RenderManager::previewFrameUpdated, - [this]() { - if (isVisible()) + &RenderManager::distantFrameUpdated, + [this](const QString& id) { + if (rendererId_ == id && isVisible()) update(QRect(0, 0, width(), height())); }); }); @@ -48,39 +46,38 @@ PreviewRenderer::~PreviewRenderer() void PreviewRenderer::paint(QPainter* painter) { - lrcInstance_->renderer() - ->drawFrame(lrc::api::video::PREVIEW_RENDERER_ID, [this, painter](QImage* previewImage) { - if (previewImage) { - painter->setRenderHint(QPainter::Antialiasing); - painter->setRenderHint(QPainter::SmoothPixmapTransform); - - auto aspectRatio = static_cast<qreal>(previewImage->width()) - / static_cast<qreal>(previewImage->height()); - auto previewHeight = height(); - auto previewWidth = previewHeight * aspectRatio; - - /* Instead of setting fixed size, we could get an x offset for the preview - * but this would render the horizontal spacers in the parent widget useless. - * e.g. - * auto parent = qobject_cast<QWidget*>(this->parent()); - * auto xPos = (parent->width() - previewWidth) / 2; - * setGeometry(QRect(QPoint(xPos, this->pos().y()), - * QSize(previewWidth, previewHeight))); - */ - setWidth(previewWidth); - setHeight(previewHeight); - - // If the given size is empty, this function returns a null image. - QImage scaledPreview; - scaledPreview = previewImage->scaled(size().toSize(), - Qt::KeepAspectRatio, - Qt::SmoothTransformation); - painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), - scaledPreview); - } else { - paintBackground(painter); - } - }); + lrcInstance_->renderer()->drawFrame(rendererId_, [this, painter](QImage* previewImage) { + if (previewImage) { + painter->setRenderHint(QPainter::Antialiasing); + painter->setRenderHint(QPainter::SmoothPixmapTransform); + + auto aspectRatio = static_cast<qreal>(previewImage->width()) + / static_cast<qreal>(previewImage->height()); + auto previewHeight = height(); + auto previewWidth = previewHeight * aspectRatio; + + /* Instead of setting fixed size, we could get an x offset for the preview + * but this would render the horizontal spacers in the parent widget useless. + * e.g. + * auto parent = qobject_cast<QWidget*>(this->parent()); + * auto xPos = (parent->width() - previewWidth) / 2; + * setGeometry(QRect(QPoint(xPos, this->pos().y()), + * QSize(previewWidth, previewHeight))); + */ + setWidth(previewWidth); + setHeight(previewHeight); + + // If the given size is empty, this function returns a null image. + QImage scaledPreview; + scaledPreview = previewImage->scaled(size().toSize(), + Qt::KeepAspectRatio, + Qt::SmoothTransformation); + painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), + scaledPreview); + } else { + paintBackground(painter); + } + }); } void @@ -103,18 +100,17 @@ VideoCallPreviewRenderer::~VideoCallPreviewRenderer() {} void VideoCallPreviewRenderer::paint(QPainter* painter) { - lrcInstance_->renderer() - ->drawFrame(lrc::api::video::PREVIEW_RENDERER_ID, [this, painter](QImage* previewImage) { - if (previewImage) { - auto scalingFactor = static_cast<qreal>(previewImage->height()) - / static_cast<qreal>(previewImage->width()); - setProperty("previewImageScalingFactor", scalingFactor); - QImage scaledPreview; - scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio); - painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), - scaledPreview); - } - }); + lrcInstance_->renderer()->drawFrame(get_rendererId(), [this, painter](QImage* previewImage) { + if (previewImage) { + auto scalingFactor = static_cast<qreal>(previewImage->height()) + / static_cast<qreal>(previewImage->width()); + setProperty("previewImageScalingFactor", scalingFactor); + QImage scaledPreview; + scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio); + painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), + scaledPreview); + } + }); } PhotoboothPreviewRender::PhotoboothPreviewRender(QQuickItem* parent) @@ -123,7 +119,7 @@ PhotoboothPreviewRender::PhotoboothPreviewRender(QQuickItem* parent) connect(this, &PreviewRenderer::lrcInstanceChanged, [this] { if (lrcInstance_) connect(lrcInstance_->renderer(), - &RenderManager::previewRenderingStopped, + &RenderManager::distantRenderingStopped, this, &PhotoboothPreviewRender::renderingStopped, Qt::UniqueConnection); @@ -133,7 +129,7 @@ PhotoboothPreviewRender::PhotoboothPreviewRender(QQuickItem* parent) QString PhotoboothPreviewRender::takePhoto(int size) { - if (auto previewImage = lrcInstance_->renderer()->getPreviewFrame()) { + if (auto previewImage = lrcInstance_->renderer()->getPreviewFrame(get_rendererId())) { return Utils::byteArrayToBase64String(Utils::QImageToByteArray(previewImage->copy())); } return {}; @@ -144,14 +140,13 @@ PhotoboothPreviewRender::paint(QPainter* painter) { painter->setRenderHint(QPainter::Antialiasing, true); - lrcInstance_->renderer() - ->drawFrame(lrc::api::video::PREVIEW_RENDERER_ID, [this, painter](QImage* previewImage) { - if (previewImage) { - QImage scaledPreview; - scaledPreview = Utils::getCirclePhoto(*previewImage, - height() <= width() ? height() : width()); - painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), - scaledPreview); - } - }); + lrcInstance_->renderer()->drawFrame(get_rendererId(), [this, painter](QImage* previewImage) { + if (previewImage) { + QImage scaledPreview; + scaledPreview = Utils::getCirclePhoto(*previewImage, + height() <= width() ? height() : width()); + painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), + scaledPreview); + } + }); } diff --git a/src/previewrenderer.h b/src/previewrenderer.h index d5d91c9c00af7295b1765ed9112427d50af4d7b3..e79551d5bfbe94b36eca3c044be8b81789c9e424 100644 --- a/src/previewrenderer.h +++ b/src/previewrenderer.h @@ -21,7 +21,7 @@ #include <QtQuick> -class LRCInstance; +#include "lrcinstance.h" /* * Use QQuickPaintedItem so that QPainter apis can be used. @@ -31,6 +31,7 @@ class PreviewRenderer : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(LRCInstance* lrcInstance MEMBER lrcInstance_ NOTIFY lrcInstanceChanged) + QML_PROPERTY(QString, rendererId); public: explicit PreviewRenderer(QQuickItem* parent = nullptr); @@ -78,7 +79,7 @@ public: Q_INVOKABLE QString takePhoto(int size); Q_SIGNALS: - void renderingStopped(); + void renderingStopped(const QString id); private: void paint(QPainter* painter) override final; diff --git a/src/rendermanager.cpp b/src/rendermanager.cpp index c483c786c7dadd4234c2373c2397ca14dc3f3fa6..87ce91c75f221f0048c0d400ae9a3d0701d6e629 100644 --- a/src/rendermanager.cpp +++ b/src/rendermanager.cpp @@ -31,9 +31,7 @@ FrameWrapper::FrameWrapper(AVModel& avModel, const QString& id) FrameWrapper::~FrameWrapper() { - if (id_ == video::PREVIEW_RENDERER_ID) { - avModel_.stopPreview(); - } + avModel_.stopPreview(id_); } void @@ -194,65 +192,40 @@ FrameWrapper::slotRenderingStopped(const QString& id) RenderManager::RenderManager(AVModel& avModel) : avModel_(avModel) -{ - previewFrameWrapper_ = std::make_unique<FrameWrapper>(avModel_); - - QObject::connect(previewFrameWrapper_.get(), - &FrameWrapper::renderingStarted, - [this](const QString& id) { - Q_UNUSED(id); - Q_EMIT previewFrameStarted(); - }); - - QObject::connect(previewFrameWrapper_.get(), - &FrameWrapper::frameUpdated, - [this](const QString& id) { - Q_UNUSED(id); - Q_EMIT previewFrameUpdated(); - }); - QObject::connect(previewFrameWrapper_.get(), - &FrameWrapper::renderingStopped, - [this](const QString& id) { - Q_UNUSED(id); - Q_EMIT previewRenderingStopped(); - }); - - previewFrameWrapper_->connectStartRendering(); -} +{} RenderManager::~RenderManager() { - previewFrameWrapper_.reset(); - for (auto& dfw : distantFrameWrapperMap_) { dfw.second.reset(); } } -bool -RenderManager::isPreviewing() -{ - return previewFrameWrapper_->isRendering(); -} - void -RenderManager::stopPreviewing() +RenderManager::stopPreviewing(const QString& id) { - previewFrameWrapper_->stopRendering(); - avModel_.stopPreview(); + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + dfwIt->second->stopRendering(); + avModel_.stopPreview(id); + } } -void -RenderManager::startPreviewing(bool force) +const QString +RenderManager::startPreviewing(const QString& id, bool force) { - if (previewFrameWrapper_->isRendering() && !force) { - return; - } + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + if (dfwIt->second->isRendering() && !force) { + return dfwIt->second->getId(); + } - if (previewFrameWrapper_->isRendering()) { - avModel_.stopPreview(); + if (dfwIt->second->isRendering()) { + avModel_.stopPreview(id); + } + return avModel_.startPreview(id); } - avModel_.startPreview(); + return ""; } void @@ -328,24 +301,21 @@ RenderManager::removeDistantRenderer(const QString& id) void RenderManager::drawFrame(const QString& id, DrawFrameCallback cb) { - if (id == lrc::api::video::PREVIEW_RENDERER_ID) { - if (previewFrameWrapper_->frameMutexTryLock()) { - cb(previewFrameWrapper_->getFrame()); - previewFrameWrapper_->frameMutexUnlock(); - } - } else { - auto dfwIt = distantFrameWrapperMap_.find(id); - if (dfwIt != distantFrameWrapperMap_.end()) { - if (dfwIt->second->frameMutexTryLock()) { - cb(dfwIt->second->getFrame()); - dfwIt->second->frameMutexUnlock(); - } + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + if (dfwIt->second->frameMutexTryLock()) { + cb(dfwIt->second->getFrame()); + dfwIt->second->frameMutexUnlock(); } } } QImage* -RenderManager::getPreviewFrame() +RenderManager::getPreviewFrame(const QString& id) { - return previewFrameWrapper_->getFrame(); + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + return dfwIt->second->getFrame(); + } + return {}; } diff --git a/src/rendermanager.h b/src/rendermanager.h index a4bf076e45367e737f7ebe12f934df5e0ff1c2bc..2c8dc669b340219436b7831321ca931e60e94c93 100644 --- a/src/rendermanager.h +++ b/src/rendermanager.h @@ -46,7 +46,7 @@ class FrameWrapper final : public QObject Q_OBJECT; public: - FrameWrapper(AVModel& avModel, const QString& id = video::PREVIEW_RENDERER_ID); + FrameWrapper(AVModel& avModel, const QString& id); ~FrameWrapper(); /* @@ -81,6 +81,11 @@ public: void frameMutexUnlock(); + const QString getId() + { + return id_; + } + Q_SIGNALS: /* * Emitted once in slotRenderingStarted. @@ -103,17 +108,17 @@ public Q_SLOTS: * Used to listen to AVModel::rendererStarted. * @param id of the renderer */ - void slotRenderingStarted(const QString& id = video::PREVIEW_RENDERER_ID); + void slotRenderingStarted(const QString& id); /* * Used to listen to AVModel::frameUpdated. * @param id of the renderer */ - void slotFrameUpdated(const QString& id = video::PREVIEW_RENDERER_ID); + void slotFrameUpdated(const QString& id); /* * Used to listen to AVModel::renderingStopped. * @param id of the renderer */ - void slotRenderingStopped(const QString& id = video::PREVIEW_RENDERER_ID); + void slotRenderingStopped(const QString& id); private: /* @@ -179,19 +184,15 @@ public: using DrawFrameCallback = std::function<void(QImage*)>; - /* - * Check if the preview is active. - */ - bool isPreviewing(); /* * Start capturing and rendering preview frames. * @param force if the capture device should be started */ - void startPreviewing(bool force = false); + const QString startPreviewing(const QString& id, bool force = false); /* * Stop capturing. */ - void stopPreviewing(); + void stopPreviewing(const QString& id); /* * Add and connect a distant renderer for a given id * to a FrameWrapper object @@ -215,25 +216,9 @@ public: * Get the most recently rendered preview frame as a QImage (none thread safe). * @return the rendered preview image */ - QImage* getPreviewFrame(); + QImage* getPreviewFrame(const QString& id = ""); Q_SIGNALS: - - /* - * Emitted when the preview the preview is started. - */ - void previewFrameStarted(); - - /* - * Emitted when the preview has a new frame ready. - */ - void previewFrameUpdated(); - - /* - * Emitted when the preview is stopped. - */ - void previewRenderingStopped(); - /* * Emitted when a distant renderer has a new frame ready for a given id. */ @@ -245,11 +230,6 @@ Q_SIGNALS: void distantRenderingStopped(const QString& id); private: - /* - * One preview frame. - */ - std::unique_ptr<FrameWrapper> previewFrameWrapper_; - /* * Distant for each call/conf/conversation. */ diff --git a/src/settingsview/SettingsView.qml b/src/settingsview/SettingsView.qml index 152a3aa7642c058555a186d6fa68da12a03a9784..d89b61cecaa040bb53221db541ee8cdb62944582 100644 --- a/src/settingsview/SettingsView.qml +++ b/src/settingsview/SettingsView.qml @@ -41,8 +41,6 @@ Rectangle { onVisibleChanged: { if(visible){ setSelected(selectedMenu,true) - } else { - AvAdapter.stopPreviewing() } } @@ -69,7 +67,6 @@ Rectangle { // slots function leaveSettingsSlot(showMainView) { - AvAdapter.stopPreviewing() settingsViewRect.stopBooth() if (showMainView) settingsViewNeedToShowMainView() diff --git a/src/settingsview/components/VideoSettings.qml b/src/settingsview/components/VideoSettings.qml index 34076e66f224a469d3cf883d54c0dde34ce58d5c..19afe5ef0b87bf5beaf8344308563ea20c4e23ef 100644 --- a/src/settingsview/components/VideoSettings.qml +++ b/src/settingsview/components/VideoSettings.qml @@ -37,7 +37,8 @@ ColumnLayout { function startPreviewing(force = false) { if (root.visible) { - AvAdapter.startPreviewing(force) + previewWidget.deviceId = VideoDevices.getDefaultDevice() + previewWidget.rendererId = VideoDevices.startDevice(previewWidget.deviceId, force) previewAvailable = true } } @@ -63,7 +64,7 @@ ColumnLayout { if (previewWidget.visible) startPreviewing(true) } else { - AvAdapter.stopPreviewing() + VideoDevices.stopDevice(previewWidget.deviceId) } } @@ -134,7 +135,7 @@ ColumnLayout { onActivated: { // TODO: start and stop preview logic in here should be in LRC - AvAdapter.stopPreviewing() + VideoDevices.stopDevice(previewWidget.deviceId) VideoDevices.setDefaultDevice(modelIndex) startPreviewing() } @@ -215,10 +216,12 @@ ColumnLayout { color: JamiTheme.primaryForegroundColor - PreviewRenderer { + DistantRenderer { id: previewWidget anchors.fill: rectBox + property string deviceId: VideoDevices.getDefaultDevice() + rendererId: VideoDevices.getDefaultDevice() lrcInstance: LRCInstance diff --git a/src/videodevices.cpp b/src/videodevices.cpp index e4d1d5dd5475669bf2526ed853a3149e7b6823f8..9cdccbed01004f8fa11eb07c36e82f5c5099126f 100644 --- a/src/videodevices.cpp +++ b/src/videodevices.cpp @@ -278,6 +278,40 @@ VideoDevices::setDefaultDevice(int index, bool useSourceModel) updateData(); } +const QString +VideoDevices::getDefaultDevice() +{ + auto idx = devicesSourceModel_->getCurrentIndex(); + auto rendererId = QString("camera://") + + devicesSourceModel_ + ->data(devicesSourceModel_->index(idx, 0), + VideoInputDeviceModel::DeviceId) + .toString(); + return rendererId; +} + +#pragma optimize("", off) +QString +VideoDevices::startDevice(const QString& deviceId, bool force) +{ + if (deviceId.isEmpty()) + return {}; + lrcInstance_->renderer()->addDistantRenderer(deviceId); + deviceOpen_ = true; + return lrcInstance_->renderer()->startPreviewing(deviceId, force); +} + +void +VideoDevices::stopDevice(const QString& deviceId, bool force) +{ + if (!deviceId.isEmpty() && (!lrcInstance_->hasActiveCall(true) || force)) { + lrcInstance_->renderer()->stopPreviewing(deviceId); + lrcInstance_->renderer()->removeDistantRenderer(deviceId); + deviceOpen_ = false; + } +} +#pragma optimize("", on) + void VideoDevices::setDefaultDeviceRes(int index) { @@ -349,6 +383,24 @@ VideoDevices::updateData() } } + if (deviceOpen_ && defaultId_ != defaultDeviceSettings.id) { + auto callId = lrcInstance_->getCurrentCallId(); + if (!callId.isEmpty()) { + auto callId = lrcInstance_->getCurrentCallId(); + auto callInfos = lrcInstance_->getCallInfo(callId, + lrcInstance_->get_currentAccountId()); + for (const auto& media : callInfos->mediaList) { + if (media["MUTED"] == "false" && media["ENABLED"] == "true" + && media["SOURCE"] == getDefaultDevice()) { + /*lrcInstance_->avModel().switchInputTo("camera://" + + defaultDeviceSettings.id, callId);*/ + // startDevice("camera://" + defaultDeviceSettings.id); + break; + } + } + } + } + set_defaultChannel(defaultDeviceSettings.channel); set_defaultId(defaultDeviceSettings.id); set_defaultName(defaultDeviceSettings.name); @@ -405,7 +457,7 @@ VideoDevices::onVideoDeviceEvent() auto& avModel = lrcInstance_->avModel(); if (currentDeviceListSize == 0) { avModel.switchInputTo({}, callId); - avModel.stopPreview(); + avModel.stopPreview(this->getDefaultDevice()); } else if (deviceEvent == DeviceEvent::Removed) { avModel.switchInputTo(defaultDevice, callId); } @@ -427,15 +479,18 @@ VideoDevices::onVideoDeviceEvent() } Q_EMIT deviceListChanged(currentDeviceListSize); - } else if (lrcInstance_->renderer()->isPreviewing()) { + } else if (deviceOpen_) { updateData(); // Use QueuedConnection to make sure that it happens at the event loop of current device Utils::oneShotConnect( lrcInstance_->renderer(), - &RenderManager::previewRenderingStopped, + &RenderManager::distantRenderingStopped, this, - [cb] { cb(); }, + [this, cb](const QString& id) { + if (this->getDefaultDevice() == id) + cb(); + }, Qt::QueuedConnection); } else { cb(); diff --git a/src/videodevices.h b/src/videodevices.h index 3ac428491a3f2a7bf7f582f5fa5cdf2061ee71c1..6322a6e5e1246cc0af7e82aad91cee70747e69ed 100644 --- a/src/videodevices.h +++ b/src/videodevices.h @@ -170,6 +170,9 @@ public: Q_INVOKABLE QVariant getScreenSharingFpsModel(); Q_INVOKABLE void setDefaultDevice(int index, bool useSourceModel = false); + Q_INVOKABLE const QString getDefaultDevice(); + Q_INVOKABLE QString startDevice(const QString& deviceId, bool force = false); + Q_INVOKABLE void stopDevice(const QString& deviceId, bool force = false); Q_INVOKABLE void setDefaultDeviceRes(int index); Q_INVOKABLE void setDefaultDeviceFps(int index); Q_INVOKABLE void setDisplayFPS(const QString& fps); @@ -209,4 +212,6 @@ private: constexpr static const char DEVICE_DESKTOP[] = "desktop"; constexpr static const char CHANNEL_DEFAULT[] = "default"; + + bool deviceOpen_ {false}; };