diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index 61e021d9c..be8ff5cb6 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -636,17 +636,17 @@ void GroupCall::subscribeToReal(not_null real) { // If we joined before you could start video and then you can, // you have to rejoin so that the server knows your video params. - real->canStartVideoValue( - ) | rpl::combine_previous( - ) | rpl::start_with_next([=](bool could, bool can) { - if (could || !can) { - return; - } if (_joinState.action == JoinAction::None) { - rejoin(); - } else { - _joinState.nextActionPending = true; - } - }, _lifetime); + //real->canStartVideoValue( // ignore can_start_video after call start. + //) | rpl::combine_previous( + //) | rpl::start_with_next([=](bool could, bool can) { + // if (could || !can) { + // return; + // } if (_joinState.action == JoinAction::None) { + // rejoin(); + // } else { + // _joinState.nextActionPending = true; + // } + //}, _lifetime); // Postpone creating video tracks, so that we know if Panel // supports OpenGL and we don't need ARGB32 frames at all. @@ -674,6 +674,10 @@ void GroupCall::subscribeToReal(not_null real) { const auto peer = data.was ? data.was->peer : data.now->peer; if (peer == _joinAs) { + const auto working = data.now && data.now->videoJoined; + if (videoIsWorking() != working) { + fillActiveVideoEndpoints(); + } return; } const auto &wasCameraEndpoint = data.was @@ -1401,6 +1405,7 @@ void GroupCall::applyMeInCallLocally() { const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0)) | (lastActive ? Flag::f_active_date : Flag(0)) | (_joinState.ssrc ? Flag(0) : Flag::f_left) + | (_videoIsWorking.current() ? Flag::f_video_joined : Flag(0)) | Flag::f_self | Flag::f_volume // Without flag the volume is reset to 100%. | Flag::f_volume_by_admin // Self volume can only be set by admin. @@ -1446,6 +1451,7 @@ void GroupCall::applyParticipantLocally( | ((participant->applyVolumeFromMin && !volume) ? Flag::f_volume_by_admin : Flag(0)) + | (participant->videoJoined ? Flag::f_video_joined : Flag(0)) | (participant->lastActive ? Flag::f_active_date : Flag(0)) | (isMuted ? Flag::f_muted : Flag(0)) | (isMutedByYou ? Flag::f_muted_by_you : Flag(0)) @@ -1884,7 +1890,9 @@ bool GroupCall::emitShareCameraError() { emitShareCameraError(error); return true; }; - if (const auto real = lookupReal(); real && !real->canStartVideo()) { + /*if (const auto real = lookupReal(); real && !real->canStartVideo()) { + return emitError(Error::DisabledNoCamera); + } else */if (!videoIsWorking()) { return emitError(Error::DisabledNoCamera); } else if (mutedByAdmin()) { return emitError(Error::MutedNoCamera); @@ -1906,7 +1914,9 @@ bool GroupCall::emitShareScreenError() { emitShareScreenError(error); return true; }; - if (const auto real = lookupReal(); real && !real->canStartVideo()) { + /*if (const auto real = lookupReal(); real && !real->canStartVideo()) { + return emitError(Error::DisabledNoScreen); + } else */if (!videoIsWorking()) { return emitError(Error::DisabledNoScreen); } else if (mutedByAdmin()) { return emitError(Error::MutedNoScreen); @@ -2377,6 +2387,16 @@ void GroupCall::fillActiveVideoEndpoints() { const auto real = lookupReal(); Assert(real != nullptr); + if (const auto participant = real->participantByPeer(_joinAs)) { + _videoIsWorking = participant->videoJoined; + } else { + _videoIsWorking = false; + } + if (!videoIsWorking()) { + toggleVideo(false); + toggleScreenSharing(std::nullopt); + } + const auto &participants = real->participants(); const auto &large = _videoEndpointLarge.current(); auto largeFound = false; @@ -2400,24 +2420,26 @@ void GroupCall::fillActiveVideoEndpoints() { } }; using Type = VideoEndpointType; - for (const auto &participant : participants) { - const auto camera = GetCameraEndpoint(participant.videoParams); - if (camera != _cameraEndpoint - && camera != _screenEndpoint - && participant.peer != _joinAs) { - const auto paused = IsCameraPaused(participant.videoParams); - feedOne({ Type::Camera, participant.peer, camera }, paused); - } - const auto screen = GetScreenEndpoint(participant.videoParams); - if (screen != _cameraEndpoint - && screen != _screenEndpoint - && participant.peer != _joinAs) { - const auto paused = IsScreenPaused(participant.videoParams); - feedOne({ Type::Screen, participant.peer, screen }, paused); + if (_videoIsWorking.current()) { + for (const auto &participant : participants) { + const auto camera = GetCameraEndpoint(participant.videoParams); + if (camera != _cameraEndpoint + && camera != _screenEndpoint + && participant.peer != _joinAs) { + const auto paused = IsCameraPaused(participant.videoParams); + feedOne({ Type::Camera, participant.peer, camera }, paused); + } + const auto screen = GetScreenEndpoint(participant.videoParams); + if (screen != _cameraEndpoint + && screen != _screenEndpoint + && participant.peer != _joinAs) { + const auto paused = IsScreenPaused(participant.videoParams); + feedOne({ Type::Screen, participant.peer, screen }, paused); + } } + feedOne({ Type::Camera, _joinAs, cameraSharingEndpoint() }, false); + feedOne({ Type::Screen, _joinAs, screenSharingEndpoint() }, false); } - feedOne({ Type::Camera, _joinAs, cameraSharingEndpoint() }, false); - feedOne({ Type::Screen, _joinAs, screenSharingEndpoint() }, false); if (large && !largeFound) { setVideoEndpointLarge({}); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 773d33828..2cae996aa 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -358,6 +358,12 @@ public: [[nodiscard]] bool mutedByAdmin() const; [[nodiscard]] bool canManage() const; [[nodiscard]] rpl::producer canManageValue() const; + [[nodiscard]] bool videoIsWorking() const { + return _videoIsWorking.current(); + } + [[nodiscard]] rpl::producer videoIsWorkingValue() const { + return _videoIsWorking.value(); + } void setCurrentAudioDevice(bool input, const QString &deviceId); void setCurrentVideoDevice(const QString &deviceId); @@ -552,6 +558,7 @@ private: rpl::variable _muted = MuteState::Muted; rpl::variable _canManage = false; + rpl::variable _videoIsWorking = false; bool _initialMuteStateSent = false; bool _acceptFields = false; diff --git a/Telegram/SourceFiles/calls/group/calls_group_menu.cpp b/Telegram/SourceFiles/calls/group/calls_group_menu.cpp index 2a1c7195a..2310b1c9d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_menu.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_menu.cpp @@ -607,7 +607,7 @@ void FillMenu( const auto addEditTitle = call->canManage(); const auto addEditRecording = call->canManage() && !real->scheduleDate(); const auto addScreenCast = !wide - && (real->canStartVideo() || call->isSharingScreen()) + && call->videoIsWorking() && !real->scheduleDate(); if (addEditJoinAs) { menu->addAction(MakeJoinAsAction( diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index b411889e1..a43acc24b 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -468,12 +468,8 @@ void Panel::refreshLeftButton() { void Panel::refreshVideoButtons(std::optional overrideWideMode) { const auto real = _call->lookupReal(); - const auto canStartVideo = !_call->scheduleDate() - && real - && real->canStartVideo(); const auto create = overrideWideMode.value_or(mode() == PanelMode::Wide) - || canStartVideo - || _call->isSharingCamera(); + || (!_call->scheduleDate() && _call->videoIsWorking()); const auto created = _video && _screenShare; if (created == create) { return; @@ -987,14 +983,14 @@ void Panel::subscribeToChanges(not_null real) { validateRecordingMark(real->recordStartDate() != 0); rpl::combine( - real->canStartVideoValue(), + _call->videoIsWorkingValue(), _call->isSharingCameraValue() ) | rpl::start_with_next([=] { refreshVideoButtons(); }, widget()->lifetime()); rpl::combine( - real->canStartVideoValue(), + _call->videoIsWorkingValue(), _call->isSharingScreenValue() ) | rpl::start_with_next([=] { refreshTopButton(); @@ -1014,8 +1010,7 @@ void Panel::refreshTopButton() { const auto hasJoinAs = _call->showChooseJoinAs(); const auto wide = (_mode.current() == PanelMode::Wide); const auto showNarrowMenu = _call->canManage() - || (real && real->canStartVideo()) - || _call->isSharingScreen(); + || _call->videoIsWorking(); const auto showNarrowUserpic = !showNarrowMenu && hasJoinAs; if (showNarrowMenu) { _joinAsToggle.destroy(); diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index 281b0fe74..06d222de5 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -590,6 +590,7 @@ void GroupCall::applyParticipantsSlice( : data.is_muted_by_you(); const auto onlyMinLoaded = data.is_min() && (!was || was->onlyMinLoaded); + const auto videoJoined = data.is_video_joined(); const auto raisedHandRating = data.vraise_hand_rating().value_or_empty(); const auto localUpdate = (sliceSource @@ -617,6 +618,7 @@ void GroupCall::applyParticipantsSlice( .mutedByMe = mutedByMe, .canSelfUnmute = canSelfUnmute, .onlyMinLoaded = onlyMinLoaded, + .videoJoined = videoJoined, }; if (i == end(_participants)) { _participantPeerByAudioSsrc.emplace( diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 9ceb3389a..9b38e05b0 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -39,6 +39,7 @@ struct GroupCallParticipant { bool mutedByMe = false; bool canSelfUnmute = false; bool onlyMinLoaded = false; + bool videoJoined = false; [[nodiscard]] const std::string &cameraEndpoint() const; [[nodiscard]] const std::string &screenEndpoint() const;