/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/weak_ptr.h" #include "base/timer.h" #include "base/bytes.h" #include "mtproto/sender.h" #include "mtproto/mtproto_auth_key.h" class History; namespace tgcalls { class GroupInstanceImpl; } // namespace tgcalls namespace base { namespace Platform { class GlobalShortcutManager; class GlobalShortcutValue; } // namespace Platform } // namespace base namespace Calls { enum class MuteState { Active, Muted, ForceMuted, }; struct LevelUpdate { uint32 ssrc = 0; float value = 0.; bool self = false; }; class GroupCall final : public base::has_weak_ptr { public: class Delegate { public: virtual ~Delegate() = default; virtual void groupCallFinished(not_null call) = 0; virtual void groupCallFailed(not_null call) = 0; }; using GlobalShortcutManager = base::Platform::GlobalShortcutManager; GroupCall( not_null delegate, not_null channel, const MTPInputGroupCall &inputCall); ~GroupCall(); [[nodiscard]] uint64 id() const { return _id; } [[nodiscard]] not_null channel() const { return _channel; } void start(); void hangup(); void discard(); void join(const MTPInputGroupCall &inputCall); void handleUpdate(const MTPGroupCall &call); void handleUpdate(const MTPDupdateGroupCallParticipants &data); void setMuted(MuteState mute); [[nodiscard]] MuteState muted() const { return _muted.current(); } [[nodiscard]] rpl::producer mutedValue() const { return _muted.value(); } enum State { Creating, Joining, Connecting, Joined, FailedHangingUp, Failed, HangingUp, Ended, }; [[nodiscard]] State state() const { return _state.current(); } [[nodiscard]] rpl::producer stateValue() const { return _state.value(); } [[nodiscard]] rpl::producer levelUpdates() const { return _levelUpdates.events(); } static constexpr auto kSpeakLevelThreshold = 0.2; void setCurrentAudioDevice(bool input, const QString &deviceId); //void setAudioVolume(bool input, float level); void setAudioDuckingEnabled(bool enabled); void toggleMute(not_null user, bool mute); std::variant> inviteUsers( const std::vector> &users); std::shared_ptr ensureGlobalShortcutManager(); void applyGlobalShortcutChanges(); [[nodiscard]] rpl::lifetime &lifetime() { return _lifetime; } private: using GlobalShortcutValue = base::Platform::GlobalShortcutValue; enum class FinishType { None, Ended, Failed, }; void handleRequestError(const RPCError &error); void handleControllerError(const QString &error); void createAndStartController(); void destroyController(); void setState(State state); void finish(FinishType type); void sendMutedUpdate(); void applySelfInCallLocally(); void rejoin(); void myLevelUpdated(float level); void audioLevelsUpdated( const std::vector> &data); void handleLevelsUpdated( gsl::span> data); void setInstanceConnected(bool connected); void checkLastSpoke(); void checkJoined(); [[nodiscard]] MTPInputGroupCall inputCall() const; const not_null _delegate; const not_null _channel; const not_null _history; MTP::Sender _api; rpl::variable _state = State::Creating; bool _instanceConnected = false; rpl::variable _muted = MuteState::Muted; bool _acceptFields = false; uint64 _id = 0; uint64 _accessHash = 0; uint32 _mySsrc = 0; mtpRequestId _createRequestId = 0; mtpRequestId _updateMuteRequestId = 0; std::unique_ptr _instance; rpl::event_stream _levelUpdates; base::flat_map _lastSpoke; base::Timer _lastSpokeCheckTimer; base::Timer _checkJoinedTimer; crl::time _lastSendProgressUpdate = 0; std::shared_ptr _shortcutManager; std::shared_ptr _pushToTalk; bool _pushToTalkStarted = false; rpl::lifetime _lifetime; }; } // namespace Calls