PageRenderTime 73ms CodeModel.GetById 53ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llimview.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 572 lines | 276 code | 117 blank | 179 comment | 4 complexity | 1207bb1979729914d1130b1abbbd7014 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file LLIMMgr.h
  3. * @brief Container for Instant Messaging
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_LLIMVIEW_H
  27. #define LL_LLIMVIEW_H
  28. #include "lldockablefloater.h"
  29. #include "lleventtimer.h"
  30. #include "llinstantmessage.h"
  31. #include "lllogchat.h"
  32. #include "llvoicechannel.h"
  33. class LLAvatarName;
  34. class LLFriendObserver;
  35. class LLCallDialogManager;
  36. class LLIMSpeakerMgr;
  37. /**
  38. * Timeout Timer for outgoing Ad-Hoc/Group IM sessions which being initialized by the server
  39. */
  40. class LLSessionTimeoutTimer : public LLEventTimer
  41. {
  42. public:
  43. LLSessionTimeoutTimer(const LLUUID& session_id, F32 period) : LLEventTimer(period), mSessionId(session_id) {}
  44. virtual ~LLSessionTimeoutTimer() {};
  45. /* virtual */ BOOL tick();
  46. private:
  47. LLUUID mSessionId;
  48. };
  49. /**
  50. * Model (MVC) for IM Sessions
  51. */
  52. class LLIMModel : public LLSingleton<LLIMModel>
  53. {
  54. public:
  55. struct LLIMSession : public boost::signals2::trackable
  56. {
  57. typedef enum e_session_type
  58. { // for now we have 4 predefined types for a session
  59. P2P_SESSION,
  60. GROUP_SESSION,
  61. ADHOC_SESSION,
  62. AVALINE_SESSION,
  63. } SType;
  64. LLIMSession(const LLUUID& session_id, const std::string& name,
  65. const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice);
  66. virtual ~LLIMSession();
  67. void sessionInitReplyReceived(const LLUUID& new_session_id);
  68. void addMessagesFromHistory(const std::list<LLSD>& history);
  69. void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false);
  70. void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
  71. /** @deprecated */
  72. static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
  73. bool isOutgoingAdHoc();
  74. bool isAdHoc();
  75. bool isP2P();
  76. bool isOtherParticipantAvaline();
  77. bool isP2PSessionType() const { return mSessionType == P2P_SESSION;}
  78. bool isAdHocSessionType() const { return mSessionType == ADHOC_SESSION;}
  79. bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;}
  80. bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;}
  81. //*TODO make private
  82. /** ad-hoc sessions involve sophisticated chat history file naming schemes */
  83. void buildHistoryFileName();
  84. LLUUID mSessionID;
  85. std::string mName;
  86. EInstantMessage mType;
  87. SType mSessionType;
  88. LLUUID mOtherParticipantID;
  89. uuid_vec_t mInitialTargetIDs;
  90. std::string mHistoryFileName;
  91. // connection to voice channel state change signal
  92. boost::signals2::connection mVoiceChannelStateChangeConnection;
  93. //does NOT include system messages and agent's messages
  94. S32 mParticipantUnreadMessageCount;
  95. // does include all incoming messages
  96. S32 mNumUnread;
  97. std::list<LLSD> mMsgs;
  98. LLVoiceChannel* mVoiceChannel;
  99. LLIMSpeakerMgr* mSpeakers;
  100. bool mSessionInitialized;
  101. //true if calling back the session URI after the session has closed is possible.
  102. //Currently this will be false only for PSTN P2P calls.
  103. bool mCallBackEnabled;
  104. bool mTextIMPossible;
  105. bool mOtherParticipantIsAvatar;
  106. bool mStartCallOnInitialize;
  107. //if IM session is created for a voice call
  108. bool mStartedAsIMCall;
  109. private:
  110. void onAdHocNameCache(const LLAvatarName& av_name);
  111. static std::string generateHash(const std::set<LLUUID>& sorted_uuids);
  112. };
  113. LLIMModel();
  114. //we should control the currently active session
  115. LLUUID mActiveSessionID;
  116. void setActiveSessionID(const LLUUID& session_id);
  117. void resetActiveSessionID() { mActiveSessionID.setNull(); }
  118. LLUUID getActiveSessionID() { return mActiveSessionID; }
  119. /** Session id to session object */
  120. std::map<LLUUID, LLIMSession*> mId2SessionMap;
  121. typedef boost::signals2::signal<void(const LLSD&)> session_signal_t;
  122. typedef boost::function<void(const LLSD&)> session_callback_t;
  123. session_signal_t mNewMsgSignal;
  124. session_signal_t mNoUnreadMsgsSignal;
  125. /**
  126. * Find an IM Session corresponding to session_id
  127. * Returns NULL if the session does not exist
  128. */
  129. LLIMSession* findIMSession(const LLUUID& session_id) const;
  130. /**
  131. * Find an Ad-Hoc IM Session with specified participants
  132. * @return first found Ad-Hoc session or NULL if the session does not exist
  133. */
  134. LLIMSession* findAdHocIMSession(const uuid_vec_t& ids);
  135. /**
  136. * Rebind session data to a new session id.
  137. */
  138. void processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id);
  139. boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); }
  140. boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); }
  141. /**
  142. * Create new session object in a model
  143. * @param name session name should not be empty, will return false if empty
  144. */
  145. bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,
  146. const uuid_vec_t& ids, bool voice = false);
  147. bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
  148. const LLUUID& other_participant_id, bool voice = false);
  149. /**
  150. * Remove all session data associated with a session specified by session_id
  151. */
  152. bool clearSession(const LLUUID& session_id);
  153. /**
  154. * Populate supplied std::list with messages starting from index specified by start_index without
  155. * emitting no unread messages signal.
  156. */
  157. void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
  158. /**
  159. * Sends no unread messages signal.
  160. */
  161. void sendNoUnreadMessages(const LLUUID& session_id);
  162. /**
  163. * Populate supplied std::list with messages starting from index specified by start_index
  164. */
  165. void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
  166. /**
  167. * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id
  168. * and also saved into a file if log2file is specified.
  169. * It sends new message signal for each added message.
  170. */
  171. bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true);
  172. /**
  173. * Similar to addMessage(...) above but won't send a signal about a new message added
  174. */
  175. LLIMModel::LLIMSession* addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
  176. const std::string& utf8_text, bool log2file = true);
  177. /**
  178. * Add a system message to an IM Model
  179. */
  180. bool proccessOnlineOfflineNotification(const LLUUID& session_id, const std::string& utf8_text);
  181. /**
  182. * Get a session's name.
  183. * For a P2P chat - it's an avatar's name,
  184. * For a group chat - it's a group's name
  185. * For an incoming ad-hoc chat - is received from the server and is in a from of "<Avatar's name> Conference"
  186. * It is updated in LLIMModel::LLIMSession's constructor to localize the "Conference".
  187. */
  188. const std::string getName(const LLUUID& session_id) const;
  189. /**
  190. * Get number of unread messages in a session with session_id
  191. * Returns -1 if the session with session_id doesn't exist
  192. */
  193. const S32 getNumUnread(const LLUUID& session_id) const;
  194. /**
  195. * Get uuid of other participant in a session with session_id
  196. * Returns LLUUID::null if the session doesn't exist
  197. *
  198. * *TODO what to do with other participants in ad-hoc and group chats?
  199. */
  200. const LLUUID& getOtherParticipantID(const LLUUID& session_id) const;
  201. /**
  202. * Get type of a session specified by session_id
  203. * Returns EInstantMessage::IM_COUNT if the session does not exist
  204. */
  205. EInstantMessage getType(const LLUUID& session_id) const;
  206. /**
  207. * Get voice channel for the session specified by session_id
  208. * Returns NULL if the session does not exist
  209. */
  210. LLVoiceChannel* getVoiceChannel(const LLUUID& session_id) const;
  211. /**
  212. * Get im speaker manager for the session specified by session_id
  213. * Returns NULL if the session does not exist
  214. */
  215. LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
  216. const std::string& getHistoryFileName(const LLUUID& session_id) const;
  217. static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
  218. static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
  219. const uuid_vec_t& ids, EInstantMessage dialog);
  220. static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing);
  221. static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id,
  222. const LLUUID& other_participant_id, EInstantMessage dialog);
  223. // Adds people from speakers list (people with whom you are currently speaking) to the Recent People List
  224. static void addSpeakersToRecent(const LLUUID& im_session_id);
  225. void testMessages();
  226. /**
  227. * Saves an IM message into a file
  228. */
  229. bool logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
  230. private:
  231. /**
  232. * Add message to a list of message associated with session specified by session_id
  233. */
  234. bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
  235. };
  236. class LLIMSessionObserver
  237. {
  238. public:
  239. virtual ~LLIMSessionObserver() {}
  240. virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0;
  241. virtual void sessionRemoved(const LLUUID& session_id) = 0;
  242. virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0;
  243. };
  244. class LLIMMgr : public LLSingleton<LLIMMgr>
  245. {
  246. friend class LLIMModel;
  247. public:
  248. enum EInvitationType
  249. {
  250. INVITATION_TYPE_INSTANT_MESSAGE = 0,
  251. INVITATION_TYPE_VOICE = 1,
  252. INVITATION_TYPE_IMMEDIATE = 2
  253. };
  254. LLIMMgr();
  255. virtual ~LLIMMgr() {};
  256. // Add a message to a session. The session can keyed to sesion id
  257. // or agent id.
  258. void addMessage(const LLUUID& session_id,
  259. const LLUUID& target_id,
  260. const std::string& from,
  261. const std::string& msg,
  262. const std::string& session_name = LLStringUtil::null,
  263. EInstantMessage dialog = IM_NOTHING_SPECIAL,
  264. U32 parent_estate_id = 0,
  265. const LLUUID& region_id = LLUUID::null,
  266. const LLVector3& position = LLVector3::zero,
  267. bool link_name = false);
  268. void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
  269. // This adds a session to the talk view. The name is the local
  270. // name of the session, dialog specifies the type of
  271. // session. Since sessions can be keyed off of first recipient or
  272. // initiator, the session can be matched against the id
  273. // provided. If the session exists, it is brought forward. This
  274. // method accepts a group id or an agent id. Specifying id = NULL
  275. // results in an im session to everyone. Returns the uuid of the
  276. // session.
  277. LLUUID addSession(const std::string& name,
  278. EInstantMessage dialog,
  279. const LLUUID& other_participant_id, bool voice = false);
  280. // Adds a session using a specific group of starting agents
  281. // the dialog type is assumed correct. Returns the uuid of the session.
  282. LLUUID addSession(const std::string& name,
  283. EInstantMessage dialog,
  284. const LLUUID& other_participant_id,
  285. const LLDynamicArray<LLUUID>& ids, bool voice = false);
  286. /**
  287. * Creates a P2P session with the requisite handle for responding to voice calls.
  288. *
  289. * @param name session name, cannot be null
  290. * @param caller_uri - sip URI of caller. It should be always be passed into the method to avoid
  291. * incorrect working of LLVoiceChannel instances. See EXT-2985.
  292. */
  293. LLUUID addP2PSession(const std::string& name,
  294. const LLUUID& other_participant_id,
  295. const std::string& voice_session_handle,
  296. const std::string& caller_uri);
  297. /**
  298. * Leave the session with session id. Send leave session notification
  299. * to the server and removes all associated session data
  300. * @return false if the session with specified id was not exist
  301. */
  302. bool leaveSession(const LLUUID& session_id);
  303. void inviteToSession(
  304. const LLUUID& session_id,
  305. const std::string& session_name,
  306. const LLUUID& caller,
  307. const std::string& caller_name,
  308. EInstantMessage type,
  309. EInvitationType inv_type,
  310. const std::string& session_handle = LLStringUtil::null,
  311. const std::string& session_uri = LLStringUtil::null);
  312. void processIMTypingStart(const LLIMInfo* im_info);
  313. void processIMTypingStop(const LLIMInfo* im_info);
  314. // automatically start a call once the session has initialized
  315. void autoStartCallOnStartup(const LLUUID& session_id);
  316. // Calc number of all unread IMs
  317. S32 getNumberOfUnreadIM();
  318. /**
  319. * Calculates number of unread IMs from real participants in all stored sessions
  320. */
  321. S32 getNumberOfUnreadParticipantMessages();
  322. // This method is used to go through all active sessions and
  323. // disable all of them. This method is usally called when you are
  324. // forced to log out or similar situations where you do not have a
  325. // good connection.
  326. void disconnectAllSessions();
  327. BOOL hasSession(const LLUUID& session_id);
  328. static LLUUID computeSessionID(EInstantMessage dialog, const LLUUID& other_participant_id);
  329. void clearPendingInvitation(const LLUUID& session_id);
  330. void processAgentListUpdates(const LLUUID& session_id, const LLSD& body);
  331. LLSD getPendingAgentListUpdates(const LLUUID& session_id);
  332. void addPendingAgentListUpdates(
  333. const LLUUID& sessioN_id,
  334. const LLSD& updates);
  335. void clearPendingAgentListUpdates(const LLUUID& session_id);
  336. void addSessionObserver(LLIMSessionObserver *);
  337. void removeSessionObserver(LLIMSessionObserver *);
  338. //show error statuses to the user
  339. void showSessionStartError(const std::string& error_string, const LLUUID session_id);
  340. void showSessionEventError(const std::string& event_string, const std::string& error_string, const LLUUID session_id);
  341. void showSessionForceClose(const std::string& reason, const LLUUID session_id);
  342. static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
  343. /**
  344. * Start call in a session
  345. * @return false if voice channel doesn't exist
  346. **/
  347. bool startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction = LLVoiceChannel::OUTGOING_CALL);
  348. /**
  349. * End call in a session
  350. * @return false if voice channel doesn't exist
  351. **/
  352. bool endCall(const LLUUID& session_id);
  353. bool isVoiceCall(const LLUUID& session_id);
  354. private:
  355. /**
  356. * Remove data associated with a particular session specified by session_id
  357. */
  358. void removeSession(const LLUUID& session_id);
  359. // This simple method just iterates through all of the ids, and
  360. // prints a simple message if they are not online. Used to help
  361. // reduce 'hello' messages to the linden employees unlucky enough
  362. // to have their calling card in the default inventory.
  363. void noteOfflineUsers(const LLUUID& session_id, const LLDynamicArray<LLUUID>& ids);
  364. void noteMutedUsers(const LLUUID& session_id, const LLDynamicArray<LLUUID>& ids);
  365. void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
  366. static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group);
  367. void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
  368. void notifyObserverSessionRemoved(const LLUUID& session_id);
  369. void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
  370. private:
  371. typedef std::list <LLIMSessionObserver *> session_observers_list_t;
  372. session_observers_list_t mSessionObservers;
  373. LLSD mPendingInvitations;
  374. LLSD mPendingAgentListUpdates;
  375. };
  376. class LLCallDialogManager : public LLInitClass<LLCallDialogManager>
  377. {
  378. public:
  379. LLCallDialogManager();
  380. ~LLCallDialogManager();
  381. static void initClass();
  382. static void onVoiceChannelChanged(const LLUUID &session_id);
  383. static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent);
  384. protected:
  385. static std::string sPreviousSessionlName;
  386. static LLIMModel::LLIMSession::SType sPreviousSessionType;
  387. static std::string sCurrentSessionlName;
  388. static LLIMModel::LLIMSession* sSession;
  389. static LLVoiceChannel::EState sOldState;
  390. };
  391. class LLCallDialog : public LLDockableFloater
  392. {
  393. public:
  394. LLCallDialog(const LLSD& payload);
  395. virtual ~LLCallDialog();
  396. virtual BOOL postBuild();
  397. void dockToToolbarButton(const std::string& toolbarButtonName);
  398. // check timer state
  399. /*virtual*/ void draw();
  400. /*virtual*/ void onOpen(const LLSD& key);
  401. protected:
  402. // lifetime timer for a notification
  403. LLTimer mLifetimeTimer;
  404. // notification's lifetime in seconds
  405. S32 mLifetime;
  406. static const S32 DEFAULT_LIFETIME = 5;
  407. virtual bool lifetimeHasExpired();
  408. virtual void onLifetimeExpired();
  409. /**
  410. * Sets icon depend on session.
  411. *
  412. * If passed session_id is a group id group icon will be shown, otherwise avatar icon for participant_id
  413. *
  414. * @param session_id - UUID of session
  415. * @param participant_id - UUID of other participant
  416. */
  417. void setIcon(const LLSD& session_id, const LLSD& participant_id);
  418. LLSD mPayload;
  419. private:
  420. LLDockControl::DocAt getDockControlPos(const std::string& toolbarButtonName);
  421. };
  422. class LLIncomingCallDialog : public LLCallDialog
  423. {
  424. public:
  425. LLIncomingCallDialog(const LLSD& payload);
  426. /*virtual*/ BOOL postBuild();
  427. /*virtual*/ void onOpen(const LLSD& key);
  428. static void onAccept(void* user_data);
  429. static void onReject(void* user_data);
  430. static void onStartIM(void* user_data);
  431. static void processCallResponse(S32 response, const LLSD& payload);
  432. private:
  433. void setCallerName(const std::string& ui_title,
  434. const std::string& ui_label,
  435. const std::string& call_type);
  436. void onAvatarNameCache(const LLUUID& agent_id,
  437. const LLAvatarName& av_name,
  438. const std::string& call_type);
  439. /*virtual*/ void onLifetimeExpired();
  440. };
  441. class LLOutgoingCallDialog : public LLCallDialog
  442. {
  443. public:
  444. LLOutgoingCallDialog(const LLSD& payload);
  445. /*virtual*/ BOOL postBuild();
  446. void show(const LLSD& key);
  447. static void onCancel(void* user_data);
  448. static const LLUUID OCD_KEY;
  449. private:
  450. // hide all text boxes
  451. void hideAllText();
  452. };
  453. // Globals
  454. extern LLIMMgr *gIMMgr;
  455. #endif // LL_LLIMView_H