PageRenderTime 81ms CodeModel.GetById 15ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 1ms

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