llvoicewebrtc.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /**
  2. * @file llvoicewebrtc.h
  3. * @brief Declaration of LLVoiceWebRTC class.
  4. *
  5. * $LicenseInfo:firstyear=2023&license=viewergpl$
  6. *
  7. * Copyright (C) 2023-2024, Linden Research, Inc.
  8. * Copyright (C) 2024, Henri Beauchamp.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #ifndef LL_LLVOICEWEBRTC_H
  34. #define LL_LLVOICEWEBRTC_H
  35. #include <list>
  36. #include <memory>
  37. #include <utility>
  38. #include "boost/function.hpp"
  39. #include "hbfastmap.h"
  40. #include "llvoiceclient.h"
  41. class LLVoiceConnection;
  42. class LLPluginClassMedia;
  43. class LLVoiceWebRTC final : public LLVoiceModule
  44. {
  45. friend class LLVoiceClient;
  46. protected:
  47. LOG_CLASS(LLVoiceWebRTC);
  48. public:
  49. LLVoiceWebRTC();
  50. ~LLVoiceWebRTC();
  51. void init();
  52. void terminate();
  53. void updateSettings();
  54. LL_INLINE bool isTerminated() const { return mTerminated; }
  55. bool isVoiceWorking() const;
  56. // LLVoiceModule overrides
  57. LL_INLINE bool isVivox() const override { return false; }
  58. LL_INLINE bool isWebRTC() const override { return true; }
  59. const std::string& getName() const override;
  60. // Returns true if the user is currently in a proximal (local spatial)
  61. // channel. Note that gestures should only fire if this returns true.
  62. LL_INLINE bool inProximalChannel() const override
  63. {
  64. return inSpatialChannel();
  65. }
  66. void setSpatialChannel(const LLSD&channel_info) override;
  67. // Note: this is synonymous to startAdHocSession() in LL's sources. HB
  68. void setNonSpatialChannel(const LLSD& channel_info,
  69. bool notify_on_first_join,
  70. bool hangup_on_last_leave) override;
  71. void leaveNonSpatialChannel() override;
  72. void leaveAudioSession() override;
  73. LL_INLINE void processChannels(bool b) override { mProcessChannels = b; }
  74. // For WebRTC, sip URI and session Id are the same thing.
  75. LL_INLINE std::string sipURIFromID(const LLUUID& id) const override
  76. {
  77. return id.asString();
  78. }
  79. #if 0 // Not used in the Cool VL Viewer
  80. void setHidden(bool hidden) override;
  81. #endif
  82. LL_INLINE LLPluginClassMedia* getPlugin() { return mWebRTCPlugin; }
  83. static void idle(void* userdatap);
  84. void setCaptureDevice(const std::string& device_id);
  85. void setRenderDevice(const std::string& device_id);
  86. typedef std::map<std::string, std::string> device_map_t;
  87. LL_INLINE const device_map_t& getCaptureDevices() const
  88. {
  89. return mCaptureDevices;
  90. }
  91. LL_INLINE const device_map_t& getRenderDevices() const
  92. {
  93. return mRenderDevices;
  94. }
  95. void setTuningMode(bool tuning_on);
  96. LL_INLINE bool inTuningMode() { return mIsInTuningMode; }
  97. LL_INLINE void tuningSetMicVolume(F32 v) { mTuningMicGain = v; }
  98. #if 0 // Not used
  99. LL_INLINE void tuningSetSpeakerVolume(F32 v) { mTuningSpeakerVolume = v; }
  100. #endif
  101. LL_INLINE F32 tuningGetEnergy() { return getAudioLevel(); }
  102. bool deviceSettingsAvailable();
  103. void refreshDeviceLists(bool clear_current_list);
  104. void leaveChannel(bool stop_talking = false);
  105. bool isCurrentChannel(const LLSD& channel_info);
  106. bool compareChannels(const LLSD& channel_info1, const LLSD& channel_info2);
  107. void setVoiceVolume(F32 volume);
  108. void setMicGain(F32 gain);
  109. // Returns -1.f when 'id' does not correspond to a participant
  110. F32 getUserVolume(const LLUUID& id);
  111. // Sets volume for specified agent, from 0-1 (where .5 is nominal)
  112. void setUserVolume(const LLUUID& id, F32 volume);
  113. void setEarLocation(S32 loc);
  114. /////////////////////////////
  115. // Accessors for data related to nearby speakers
  116. bool getIsSpeaking(const LLUUID& id);
  117. // true if we have received data for this avatar.
  118. bool getVoiceEnabled(const LLUUID& id);
  119. // "power" is related to "amplitude" in a defined way. I am just not sure
  120. // what the formula is...
  121. // Note: changed to return -1.f when 'id' is not in session. HB
  122. F32 getCurrentPower(const LLUUID& id);
  123. bool getIsModeratorMuted(const LLUUID& id);
  124. class participantState
  125. {
  126. public:
  127. LL_INLINE participantState(const LLUUID& av_id,
  128. const LLUUID& region_id)
  129. : mAvatarID(av_id),
  130. mRegion(region_id),
  131. mURI(av_id.asString()),
  132. mLevel(0.f),
  133. mVolume(0.5f),
  134. mIsSpeaking(false),
  135. mIsModeratorMuted(false),
  136. mIsMuted(false)
  137. {
  138. }
  139. public:
  140. LLUUID mAvatarID;
  141. LLUUID mRegion;
  142. std::string mURI;
  143. std::string mLegacyName;
  144. // The current audio level of the participant
  145. F32 mLevel;
  146. // The gain applied to the participant
  147. F32 mVolume;
  148. bool mIsSpeaking;
  149. bool mIsModeratorMuted;
  150. bool mIsMuted;
  151. };
  152. typedef std::shared_ptr<participantState> pstate_ptr_t;
  153. typedef fast_hmap<LLUUID, pstate_ptr_t> particip_map_t;
  154. particip_map_t* getParticipantList();
  155. pstate_ptr_t findParticipantByID(const std::string& channel_id,
  156. const LLUUID& id);
  157. pstate_ptr_t addParticipantByID(const std::string& channel_id,
  158. const LLUUID& id, const LLUUID& region_id);
  159. void removeParticipantByID(const std::string& channel_id,
  160. const LLUUID& id, const LLUUID& region_id);
  161. bool isParticipant(const LLUUID& id);
  162. bool isCallBackPossible(const LLUUID& session_id);
  163. #if 0 // Not used in the Cool VL Viewer
  164. void addObserver(LLVoiceClientParticipantObserver* observerp);
  165. void removeObserver(LLVoiceClientParticipantObserver* observerp);
  166. #endif
  167. void onConnectionEstablished(const std::string& channel_id,
  168. const LLUUID& region_id);
  169. void onConnectionShutDown(const std::string& channel_id,
  170. const LLUUID& region_id);
  171. void onConnectionFailure(const std::string& channel_id,
  172. const LLUUID& region_id,
  173. LLVoiceClientStatusObserver::EStatusType status =
  174. LLVoiceClientStatusObserver::ERROR_UNKNOWN);
  175. void updatePosition();
  176. void sendPositionUpdate(bool force);
  177. void updateOwnVolume();
  178. void addObserver(LLVoiceClientStatusObserver* observerp);
  179. void removeObserver(LLVoiceClientStatusObserver* observerp);
  180. bool answerInvite(std::string& session_handle);
  181. // Used in mute list observer
  182. void muteListChanged();
  183. private:
  184. class sessionState
  185. {
  186. protected:
  187. LOG_CLASS(LLVoiceWebRTC::sessionState);
  188. sessionState();
  189. public:
  190. virtual ~sessionState();
  191. virtual bool isSpatial() = 0;
  192. virtual bool isEstate() = 0;
  193. virtual bool isCallbackPossible() = 0;
  194. virtual bool processConnectionStates();
  195. virtual void sendData(const std::string& data);
  196. typedef std::shared_ptr<sessionState> ptr_t;
  197. typedef std::weak_ptr<sessionState> wptr_t;
  198. typedef boost::function<void(const ptr_t &)> func_t;
  199. pstate_ptr_t addParticipant(const LLUUID& av_id,
  200. const LLUUID& region_id);
  201. void removeParticipant(pstate_ptr_t participantp);
  202. void removeAllParticipants(const LLUUID& region_id);
  203. pstate_ptr_t findParticipantByID(const LLUUID& id);
  204. void shutdownAllConnections();
  205. void reconnectAllSessions();
  206. #if 0 // Reviving a session does not properly work: do not allow it ! HB
  207. LL_INLINE void revive() { mShuttingDown = false; }
  208. #endif
  209. bool isEmpty();
  210. void setMuteMic(bool muted);
  211. void setMicGain(F32 volume);
  212. void setSpeakerVolume(F32 volume);
  213. void setUserVolume(const LLUUID& id, F32 volume);
  214. void setUserMute(const LLUUID& id, bool mute);
  215. void muteListChanged();
  216. static void addSession(const std::string& channel_id, ptr_t& sessionp);
  217. static bool hasSession(const std::string& session_id);
  218. static ptr_t matchSessionByChannelID(const std::string& channel_id);
  219. static void processSessionStates();
  220. static void reapEmptySessions();
  221. static void forEach(func_t fn);
  222. private:
  223. static void forEachPredicate(const std::pair<std::string, wptr_t>& a,
  224. func_t fn);
  225. protected:
  226. std::list<std::shared_ptr<LLVoiceConnection> > mConnections;
  227. private:
  228. // Canonical list of outstanding sessions.
  229. typedef fast_hmap<std::string, ptr_t> map_t;
  230. static map_t sSessions;
  231. public:
  232. std::string mHandle;
  233. std::string mChannelID;
  234. std::string mName;
  235. particip_map_t mParticipantsByUUID;
  236. F32 mSpeakerVolume;
  237. bool mMuted;
  238. bool mHangupOnLastLeave;
  239. bool mNotifyOnFirstJoin;
  240. bool mShuttingDown;
  241. };
  242. class estateSessionState final : public sessionState
  243. {
  244. protected:
  245. LOG_CLASS(LLVoiceWebRTC::estateSessionState);
  246. public:
  247. estateSessionState();
  248. bool processConnectionStates() override;
  249. LL_INLINE bool isSpatial() override { return true; }
  250. LL_INLINE bool isEstate() override { return true; }
  251. LL_INLINE bool isCallbackPossible() override { return false; }
  252. };
  253. class parcelSessionState final : public sessionState
  254. {
  255. protected:
  256. LOG_CLASS(LLVoiceWebRTC::estateSessionState);
  257. public:
  258. parcelSessionState(const std::string& channel_id, S32 parcel_id);
  259. LL_INLINE bool isSpatial() override { return true; }
  260. LL_INLINE bool isEstate() override { return false; }
  261. LL_INLINE bool isCallbackPossible() override { return false; }
  262. };
  263. class adhocSessionState final : public sessionState
  264. {
  265. protected:
  266. LOG_CLASS(LLVoiceWebRTC::adhocSessionState);
  267. public:
  268. adhocSessionState(const std::string& channel_id,
  269. const std::string& credentials,
  270. bool notify_on_first_join,
  271. bool hangup_on_last_leave);
  272. LL_INLINE bool isSpatial() override { return true; }
  273. LL_INLINE bool isEstate() override { return false; }
  274. LL_INLINE bool isCallbackPossible() override
  275. {
  276. return mNotifyOnFirstJoin && mHangupOnLastLeave;
  277. }
  278. protected:
  279. std::string mCredentials;
  280. };
  281. sessionState::ptr_t findP2PSession(const LLUUID& id);
  282. sessionState::ptr_t addSession(const std::string& channel_id,
  283. sessionState::ptr_t session);
  284. void deleteSession(const sessionState::ptr_t& sessionp);
  285. void setVoiceEnabled(bool enabled);
  286. void setMuteMic(bool muted);
  287. #if 0 // Not used in the Cool VL Viewer
  288. void setHidden(bool hidden) override;
  289. #endif
  290. LL_INLINE void clearCaptureDevices() { mCaptureDevices.clear(); }
  291. void addCaptureDevice(const std::string& display_name,
  292. const std::string& device_id);
  293. LL_INLINE void clearRenderDevices() { mRenderDevices.clear(); }
  294. void addRenderDevice(const std::string& display_name,
  295. const std::string& device_id);
  296. void voiceConnectionCoro();
  297. void cleanUp();
  298. void lookupName(const LLUUID& id);
  299. static void onAvatarNameLookup(const LLUUID& id,
  300. const std::string& fullname, bool);
  301. void avatarNameResolved(const LLUUID& id, const std::string& name);
  302. static void predAvatarName(const sessionState::ptr_t& sessionp,
  303. const LLUUID& id, const std::string& name);
  304. /////////////////////////////
  305. // Sending updates of current state
  306. void setListenerPosition(const LLVector3d& position,
  307. const LLVector3& velocity,
  308. const LLQuaternion& rot);
  309. void setAvatarPosition(const LLVector3d& position,
  310. const LLVector3& velocity,
  311. const LLQuaternion& rot);
  312. void startEstateSession();
  313. void startParcelSession(const std::string& channel_id, S32 parcel_id);
  314. bool inSpatialChannel() const;
  315. bool inOrJoiningChannel(const std::string& channel_id);
  316. bool inEstateChannel();
  317. LLSD getAudioSessionChannelInfo();
  318. void enforceTether();
  319. void updateNeighboringRegions();
  320. LL_INLINE const uuid_list_t& getNeighboringRegions() const
  321. {
  322. return mNeighboringRegions;
  323. }
  324. #if 0 // Not used in the Cool VL Viewer
  325. void notifyParticipantObservers();
  326. #endif
  327. void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
  328. F32 getAudioLevel();
  329. bool launchPlugin();
  330. void killPlugin();
  331. void checkDevicesChanged();
  332. static void predSendData(const sessionState::ptr_t& sessionp,
  333. const std::string& spatial_data);
  334. static void predUpdateOwnVolume(const sessionState::ptr_t& sessionp,
  335. F32 audio_level);
  336. static void predSetMuteMic(const sessionState::ptr_t& sessionp, bool mute);
  337. static void predSetSpeakerVolume(const sessionState::ptr_t& sessionp,
  338. F32 volume);
  339. static void predShutdownSession(const sessionState::ptr_t& sessionp);
  340. static void predReconnect(const sessionState::ptr_t& sessionp);
  341. static void predSetUserVolume(const sessionState::ptr_t& sessionp,
  342. const LLUUID& id, F32 volume);
  343. static void predMuteListChanged(const sessionState::ptr_t& sessionp);
  344. private:
  345. LLPluginClassMedia* mWebRTCPlugin;
  346. // Session state for the current audio session
  347. sessionState::ptr_t mSession;
  348. // Session state for the audio session we are trying to join
  349. sessionState::ptr_t mNextSession;
  350. enum
  351. {
  352. earLocCamera = 0, // Ear at camera
  353. earLocAvatar, // Ear at avatar
  354. earLocMixed // Ear at avatar location/camera direction
  355. };
  356. S32 mEarLocation;
  357. F32 mSpeakerVolume;
  358. F32 mMicGain;
  359. F32 mTuningMicGain;
  360. S32 mTuningSpeakerVolume;
  361. std::string mSpatialSessionCredentials;
  362. device_map_t mCaptureDevices;
  363. device_map_t mRenderDevices;
  364. LLVector3d mListenerPosition;
  365. LLVector3d mListenerRequestedPosition;
  366. LLVector3 mListenerVelocity;
  367. LLQuaternion mListenerRot;
  368. LLVector3d mAvatarPosition;
  369. LLVector3 mAvatarVelocity;
  370. LLQuaternion mAvatarRot;
  371. uuid_list_t mNeighboringRegions;
  372. typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
  373. status_observer_set_t mStatusObservers;
  374. bool mTerminated;
  375. bool mInitDone;
  376. bool mIsCoroutineActive;
  377. bool mVoiceEnabled;
  378. bool mProcessChannels;
  379. bool mIsProcessingChannels;
  380. bool mPluginHasDied;
  381. bool mIsInTuningMode;
  382. bool mMuteMic;
  383. bool mSpatialCoordsDirty;
  384. };
  385. // Note: since this is a global class instance, all class members are always
  386. // available, from viewer launch to _exit(): no need for static variables to
  387. // track the shutdown (or ready) state ! HB
  388. extern LLVoiceWebRTC gVoiceWebRTC;
  389. #endif //LL_LLVOICEWEBRTC_H