[Voice Update] Break out llvoicechannel.* from llimpanel.*
This commit is contained in:
@@ -519,6 +519,7 @@ set(viewer_SOURCE_FILES
|
||||
llvoclouds.cpp
|
||||
llvograss.cpp
|
||||
llvoground.cpp
|
||||
llvoicechannel.cpp
|
||||
llvoiceclient.cpp
|
||||
llvoiceremotectrl.cpp
|
||||
llvoicevisualizer.cpp
|
||||
@@ -1024,6 +1025,7 @@ set(viewer_HEADER_FILES
|
||||
llvoclouds.h
|
||||
llvograss.h
|
||||
llvoground.h
|
||||
llvoicechannel.h
|
||||
llvoiceclient.h
|
||||
llvoiceremotectrl.h
|
||||
llvoicevisualizer.h
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
#include "llfirstuse.h"
|
||||
#include "llrender.h"
|
||||
#include "llvector4a.h"
|
||||
#include "llimpanel.h" // For LLVoiceClient and LLVoiceChannel
|
||||
#include "llvoicechannel.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llprogressview.h"
|
||||
#include "llvocache.h"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "llappviewer.h"
|
||||
#include "llavataractions.h"
|
||||
#include "llbutton.h"
|
||||
#include "llimpanel.h" // LLVoiceChannel
|
||||
#include "llimpanel.h" // LLFloaterIMPanel
|
||||
#include "llimview.h"
|
||||
#include "llmutelist.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llworld.h"
|
||||
|
||||
// [RLVa:KB]
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "llfloaterchat.h"
|
||||
#include "llfloaterfriends.h"
|
||||
#include "llfloatergroups.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llimview.h"
|
||||
#include "llimpanel.h"
|
||||
#include "llstring.h"
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
#include "llprefsvoice.h"
|
||||
#include "llsliderctrl.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llvoiceclient.h"
|
||||
#include "llimpanel.h"
|
||||
|
||||
// Library includes (after viewer)
|
||||
#include "lluictrlfactory.h"
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* @brief LLIMPanel class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
@@ -71,6 +70,7 @@
|
||||
#include "llviewercontrol.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "lllogchat.h"
|
||||
#include "llweb.h"
|
||||
#include "llhttpclient.h"
|
||||
@@ -86,7 +86,6 @@
|
||||
|
||||
class AIHTTPTimeoutPolicy;
|
||||
extern AIHTTPTimeoutPolicy startConferenceChatResponder_timeout;
|
||||
extern AIHTTPTimeoutPolicy voiceCallCapResponder_timeout;
|
||||
extern AIHTTPTimeoutPolicy sessionInviteResponder_timeout;
|
||||
|
||||
//
|
||||
@@ -95,7 +94,6 @@ extern AIHTTPTimeoutPolicy sessionInviteResponder_timeout;
|
||||
const S32 LINE_HEIGHT = 16;
|
||||
const S32 MIN_WIDTH = 200;
|
||||
const S32 MIN_HEIGHT = 130;
|
||||
const U32 DEFAULT_RETRIES_COUNT = 3;
|
||||
|
||||
//
|
||||
// Statics
|
||||
@@ -105,13 +103,6 @@ static std::string sTitleString = "Instant Message with [NAME]";
|
||||
static std::string sTypingStartString = "[NAME]: ...";
|
||||
static std::string sSessionStartString = "Starting session with [NAME] please wait.";
|
||||
|
||||
LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
|
||||
LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
|
||||
LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
|
||||
LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
|
||||
|
||||
BOOL LLVoiceChannel::sSuspended = FALSE;
|
||||
|
||||
void session_starter_helper(
|
||||
const LLUUID& temp_session_id,
|
||||
const LLUUID& other_participant_id,
|
||||
@@ -300,792 +291,6 @@ bool send_start_session_messages(
|
||||
return false;
|
||||
}
|
||||
|
||||
class LLVoiceCallCapResponder : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
public:
|
||||
LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
|
||||
|
||||
/*virtual*/ void error(U32 status, const std::string& reason); // called with bad status codes
|
||||
/*virtual*/ void result(const LLSD& content);
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return voiceCallCapResponder_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "LLVoiceCallCapResponder"; }
|
||||
|
||||
private:
|
||||
LLUUID mSessionID;
|
||||
};
|
||||
|
||||
|
||||
void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
|
||||
{
|
||||
llwarns << "LLVoiceCallCapResponder::error("
|
||||
<< status << ": " << reason << ")"
|
||||
<< llendl;
|
||||
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
|
||||
if ( channelp )
|
||||
{
|
||||
if ( 403 == status )
|
||||
{
|
||||
//403 == no ability
|
||||
LLNotifications::instance().add(
|
||||
"VoiceNotAllowed",
|
||||
channelp->getNotifyArgs());
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotifications::instance().add(
|
||||
"VoiceCallGenericError",
|
||||
channelp->getNotifyArgs());
|
||||
}
|
||||
channelp->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceCallCapResponder::result(const LLSD& content)
|
||||
{
|
||||
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
|
||||
if (channelp)
|
||||
{
|
||||
// *TODO: DEBUG SPAM
|
||||
LLSD::map_const_iterator iter;
|
||||
for(iter = content.beginMap(); iter != content.endMap(); ++iter)
|
||||
{
|
||||
llinfos << "LLVoiceCallCapResponder::result got "
|
||||
<< iter->first << llendl;
|
||||
}
|
||||
|
||||
channelp->setChannelInfo(
|
||||
content["voice_credentials"]["channel_uri"].asString(),
|
||||
content["voice_credentials"]["channel_credentials"].asString());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLVoiceChannel
|
||||
//
|
||||
LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) :
|
||||
mSessionID(session_id),
|
||||
mState(STATE_NO_CHANNEL_INFO),
|
||||
mSessionName(session_name),
|
||||
mIgnoreNextSessionLeave(FALSE)
|
||||
{
|
||||
mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
|
||||
|
||||
if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
|
||||
{
|
||||
// a voice channel already exists for this session id, so this instance will be orphaned
|
||||
// the end result should simply be the failure to make voice calls
|
||||
llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
|
||||
}
|
||||
|
||||
LLVoiceClient::getInstance()->addObserver(this);
|
||||
}
|
||||
|
||||
LLVoiceChannel::~LLVoiceChannel()
|
||||
{
|
||||
// Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
|
||||
if(gVoiceClient)
|
||||
{
|
||||
gVoiceClient->removeObserver(this);
|
||||
}
|
||||
|
||||
sVoiceChannelMap.erase(mSessionID);
|
||||
sVoiceChannelURIMap.erase(mURI);
|
||||
}
|
||||
|
||||
void LLVoiceChannel::setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials)
|
||||
{
|
||||
setURI(uri);
|
||||
|
||||
mCredentials = credentials;
|
||||
|
||||
if (mState == STATE_NO_CHANNEL_INFO)
|
||||
{
|
||||
if (mURI.empty())
|
||||
{
|
||||
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
|
||||
llwarns << "Received empty URI for channel " << mSessionName << llendl;
|
||||
deactivate();
|
||||
}
|
||||
else if (mCredentials.empty())
|
||||
{
|
||||
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
|
||||
llwarns << "Received empty credentials for channel " << mSessionName << llendl;
|
||||
deactivate();
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(STATE_READY);
|
||||
|
||||
// if we are supposed to be active, reconnect
|
||||
// this will happen on initial connect, as we request credentials on first use
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
// just in case we got new channel info while active
|
||||
// should move over to new channel
|
||||
activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
|
||||
{
|
||||
if (channelURI != mURI)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < BEGIN_ERROR_STATUS)
|
||||
{
|
||||
handleStatusChange(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleError(type);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::handleStatusChange(EStatusType type)
|
||||
{
|
||||
// status updates
|
||||
switch(type)
|
||||
{
|
||||
case STATUS_LOGIN_RETRY:
|
||||
//mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
|
||||
LLNotificationsUtil::add("VoiceLoginRetry");
|
||||
break;
|
||||
case STATUS_LOGGED_IN:
|
||||
//if (!mLoginNotificationHandle.isDead())
|
||||
//{
|
||||
// LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
|
||||
// if (notifyp)
|
||||
// {
|
||||
// notifyp->close();
|
||||
// }
|
||||
// mLoginNotificationHandle.markDead();
|
||||
//}
|
||||
break;
|
||||
case STATUS_LEFT_CHANNEL:
|
||||
if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
|
||||
{
|
||||
// if forceably removed from channel
|
||||
// update the UI and revert to default channel
|
||||
LLNotificationsUtil::add("VoiceChannelDisconnected", mNotifyArgs);
|
||||
deactivate();
|
||||
}
|
||||
mIgnoreNextSessionLeave = FALSE;
|
||||
break;
|
||||
case STATUS_JOINING:
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_RINGING);
|
||||
}
|
||||
break;
|
||||
case STATUS_JOINED:
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_CONNECTED);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// default behavior is to just deactivate channel
|
||||
// derived classes provide specific error messages
|
||||
void LLVoiceChannel::handleError(EStatusType type)
|
||||
{
|
||||
deactivate();
|
||||
setState(STATE_ERROR);
|
||||
}
|
||||
|
||||
BOOL LLVoiceChannel::isActive()
|
||||
{
|
||||
// only considered active when currently bound channel matches what our channel
|
||||
return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
|
||||
}
|
||||
|
||||
BOOL LLVoiceChannel::callStarted()
|
||||
{
|
||||
return mState >= STATE_CALL_STARTED;
|
||||
}
|
||||
|
||||
void LLVoiceChannel::deactivate()
|
||||
{
|
||||
if (mState >= STATE_RINGING)
|
||||
{
|
||||
// ignore session leave event
|
||||
mIgnoreNextSessionLeave = TRUE;
|
||||
}
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_HUNG_UP);
|
||||
// mute the microphone if required when returning to the proximal channel
|
||||
if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
|
||||
{
|
||||
gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
// default channel is proximal channel
|
||||
sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
|
||||
sCurrentVoiceChannel->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::activate()
|
||||
{
|
||||
if (callStarted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// deactivate old channel and mark ourselves as the active one
|
||||
if (sCurrentVoiceChannel != this)
|
||||
{
|
||||
// mark as current before deactivating the old channel to prevent
|
||||
// activating the proximal channel between IM calls
|
||||
LLVoiceChannel* old_channel = sCurrentVoiceChannel;
|
||||
sCurrentVoiceChannel = this;
|
||||
if (old_channel)
|
||||
{
|
||||
old_channel->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
if (mState == STATE_NO_CHANNEL_INFO)
|
||||
{
|
||||
// responsible for setting status to active
|
||||
getChannelInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(STATE_CALL_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::getChannelInfo()
|
||||
{
|
||||
// pretend we have everything we need
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
setState(STATE_CALL_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
|
||||
{
|
||||
voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
|
||||
if (found_it == sVoiceChannelMap.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return found_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
|
||||
{
|
||||
voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
|
||||
if (found_it == sVoiceChannelURIMap.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return found_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
|
||||
{
|
||||
sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
|
||||
mSessionID = new_session_id;
|
||||
sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
|
||||
}
|
||||
|
||||
void LLVoiceChannel::setURI(std::string uri)
|
||||
{
|
||||
sVoiceChannelURIMap.erase(mURI);
|
||||
mURI = uri;
|
||||
sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
|
||||
}
|
||||
|
||||
void LLVoiceChannel::setState(EState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case STATE_RINGING:
|
||||
gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
|
||||
break;
|
||||
case STATE_CONNECTED:
|
||||
gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
|
||||
break;
|
||||
case STATE_HUNG_UP:
|
||||
gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mState = state;
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
void LLVoiceChannel::initClass()
|
||||
{
|
||||
sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
void LLVoiceChannel::suspend()
|
||||
{
|
||||
if (!sSuspended)
|
||||
{
|
||||
sSuspendedVoiceChannel = sCurrentVoiceChannel;
|
||||
sSuspended = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVoiceChannel::resume()
|
||||
{
|
||||
if (sSuspended)
|
||||
{
|
||||
if (gVoiceClient->voiceEnabled())
|
||||
{
|
||||
if (sSuspendedVoiceChannel)
|
||||
{
|
||||
sSuspendedVoiceChannel->activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVoiceChannelProximal::getInstance()->activate();
|
||||
}
|
||||
}
|
||||
sSuspended = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLVoiceChannelGroup
|
||||
//
|
||||
|
||||
LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
|
||||
LLVoiceChannel(session_id, session_name)
|
||||
{
|
||||
mRetries = DEFAULT_RETRIES_COUNT;
|
||||
mIsRetrying = FALSE;
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::deactivate()
|
||||
{
|
||||
if (callStarted())
|
||||
{
|
||||
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
|
||||
}
|
||||
LLVoiceChannel::deactivate();
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::activate()
|
||||
{
|
||||
if (callStarted()) return;
|
||||
|
||||
LLVoiceChannel::activate();
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
// we have the channel info, just need to use it now
|
||||
LLVoiceClient::getInstance()->setNonSpatialChannel(
|
||||
mURI,
|
||||
mCredentials);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::getChannelInfo()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
std::string url = region->getCapability("ChatSessionRequest");
|
||||
LLSD data;
|
||||
data["method"] = "call";
|
||||
data["session-id"] = mSessionID;
|
||||
LLHTTPClient::post(url,
|
||||
data,
|
||||
new LLVoiceCallCapResponder(mSessionID));
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials)
|
||||
{
|
||||
setURI(uri);
|
||||
|
||||
mCredentials = credentials;
|
||||
|
||||
if (mState == STATE_NO_CHANNEL_INFO)
|
||||
{
|
||||
if(!mURI.empty() && !mCredentials.empty())
|
||||
{
|
||||
setState(STATE_READY);
|
||||
|
||||
// if we are supposed to be active, reconnect
|
||||
// this will happen on initial connect, as we request credentials on first use
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
// just in case we got new channel info while active
|
||||
// should move over to new channel
|
||||
activate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// *TODO: notify user
|
||||
llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
else if ( mIsRetrying )
|
||||
{
|
||||
// we have the channel info, just need to use it now
|
||||
LLVoiceClient::getInstance()->setNonSpatialChannel(
|
||||
mURI,
|
||||
mCredentials);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
|
||||
{
|
||||
// status updates
|
||||
switch(type)
|
||||
{
|
||||
case STATUS_JOINED:
|
||||
mRetries = 3;
|
||||
mIsRetrying = FALSE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleStatusChange(type);
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::handleError(EStatusType status)
|
||||
{
|
||||
std::string notify;
|
||||
switch(status)
|
||||
{
|
||||
case ERROR_CHANNEL_LOCKED:
|
||||
case ERROR_CHANNEL_FULL:
|
||||
notify = "VoiceChannelFull";
|
||||
break;
|
||||
case ERROR_NOT_AVAILABLE:
|
||||
//clear URI and credentials
|
||||
//set the state to be no info
|
||||
//and activate
|
||||
if ( mRetries > 0 )
|
||||
{
|
||||
mRetries--;
|
||||
mIsRetrying = TRUE;
|
||||
mIgnoreNextSessionLeave = TRUE;
|
||||
|
||||
getChannelInfo();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
notify = "VoiceChannelJoinFailed";
|
||||
mRetries = DEFAULT_RETRIES_COUNT;
|
||||
mIsRetrying = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ERROR_UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// notification
|
||||
if (!notify.empty())
|
||||
{
|
||||
LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
|
||||
// echo to im window
|
||||
gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleError(status);
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::setState(EState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case STATE_RINGING:
|
||||
if ( !mIsRetrying )
|
||||
{
|
||||
gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
|
||||
}
|
||||
|
||||
mState = state;
|
||||
break;
|
||||
default:
|
||||
LLVoiceChannel::setState(state);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLVoiceChannelProximal
|
||||
//
|
||||
LLVoiceChannelProximal::LLVoiceChannelProximal() :
|
||||
LLVoiceChannel(LLUUID::null, LLStringUtil::null)
|
||||
{
|
||||
activate();
|
||||
}
|
||||
|
||||
BOOL LLVoiceChannelProximal::isActive()
|
||||
{
|
||||
return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::activate()
|
||||
{
|
||||
if (callStarted()) return;
|
||||
|
||||
LLVoiceChannel::activate();
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
// this implicitly puts you back in the spatial channel
|
||||
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
|
||||
{
|
||||
if (!proximal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < BEGIN_ERROR_STATUS)
|
||||
{
|
||||
handleStatusChange(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleError(type);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
|
||||
{
|
||||
// status updates
|
||||
switch(status)
|
||||
{
|
||||
case STATUS_LEFT_CHANNEL:
|
||||
// do not notify user when leaving proximal channel
|
||||
return;
|
||||
case STATUS_VOICE_DISABLED:
|
||||
gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
LLVoiceChannel::handleStatusChange(status);
|
||||
}
|
||||
|
||||
|
||||
void LLVoiceChannelProximal::handleError(EStatusType status)
|
||||
{
|
||||
std::string notify;
|
||||
switch(status)
|
||||
{
|
||||
case ERROR_CHANNEL_LOCKED:
|
||||
case ERROR_CHANNEL_FULL:
|
||||
notify = "ProximalVoiceChannelFull";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// notification
|
||||
if (!notify.empty())
|
||||
{
|
||||
LLNotifications::instance().add(notify, mNotifyArgs);
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleError(status);
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::deactivate()
|
||||
{
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_HUNG_UP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLVoiceChannelP2P
|
||||
//
|
||||
LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
|
||||
LLVoiceChannelGroup(session_id, session_name),
|
||||
mOtherUserID(other_user_id),
|
||||
mReceivedCall(FALSE)
|
||||
{
|
||||
// make sure URI reflects encoded version of other user's agent id
|
||||
setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
|
||||
{
|
||||
// status updates
|
||||
switch(type)
|
||||
{
|
||||
case STATUS_LEFT_CHANNEL:
|
||||
if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
|
||||
{
|
||||
if (mState == STATE_RINGING)
|
||||
{
|
||||
// other user declined call
|
||||
LLNotificationsUtil::add("P2PCallDeclined", mNotifyArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// other user hung up
|
||||
LLNotificationsUtil::add("VoiceChannelDisconnectedP2P", mNotifyArgs);
|
||||
}
|
||||
deactivate();
|
||||
}
|
||||
mIgnoreNextSessionLeave = FALSE;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleStatusChange(type);
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::handleError(EStatusType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ERROR_NOT_AVAILABLE:
|
||||
LLNotificationsUtil::add("P2PCallNoAnswer", mNotifyArgs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleError(type);
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::activate()
|
||||
{
|
||||
if (callStarted()) return;
|
||||
|
||||
LLVoiceChannel::activate();
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
// no session handle yet, we're starting the call
|
||||
if (mSessionHandle.empty())
|
||||
{
|
||||
mReceivedCall = FALSE;
|
||||
LLVoiceClient::getInstance()->callUser(mOtherUserID);
|
||||
}
|
||||
// otherwise answering the call
|
||||
else
|
||||
{
|
||||
LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
|
||||
|
||||
// using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
|
||||
mSessionHandle.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::getChannelInfo()
|
||||
{
|
||||
// pretend we have everything we need, since P2P doesn't use channel info
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
setState(STATE_CALL_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
// receiving session from other user who initiated call
|
||||
void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
|
||||
{
|
||||
BOOL needs_activate = FALSE;
|
||||
if (callStarted())
|
||||
{
|
||||
// defer to lower agent id when already active
|
||||
if (mOtherUserID < gAgent.getID())
|
||||
{
|
||||
// pretend we haven't started the call yet, so we can connect to this session instead
|
||||
deactivate();
|
||||
needs_activate = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are active and have priority, invite the other user again
|
||||
// under the assumption they will join this new session
|
||||
mSessionHandle.clear();
|
||||
LLVoiceClient::getInstance()->callUser(mOtherUserID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mSessionHandle = handle;
|
||||
|
||||
// The URI of a p2p session should always be the other end's SIP URI.
|
||||
if(!inURI.empty())
|
||||
{
|
||||
setURI(inURI);
|
||||
}
|
||||
else
|
||||
{
|
||||
setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
|
||||
}
|
||||
|
||||
mReceivedCall = TRUE;
|
||||
|
||||
if (needs_activate)
|
||||
{
|
||||
activate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::setState(EState state)
|
||||
{
|
||||
// you only "answer" voice invites in p2p mode
|
||||
// so provide a special purpose message here
|
||||
if (mReceivedCall && state == STATE_RINGING)
|
||||
{
|
||||
gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
|
||||
mState = state;
|
||||
return;
|
||||
}
|
||||
LLVoiceChannel::setState(state);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLFloaterIMPanel
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* @brief LLIMPanel class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
@@ -50,131 +49,7 @@ class LLIMSpeakerMgr;
|
||||
class LLPanelActiveSpeakers;
|
||||
class LLPanel;
|
||||
class LLButton;
|
||||
|
||||
class LLVoiceChannel : public LLVoiceClientStatusObserver
|
||||
{
|
||||
public:
|
||||
typedef enum e_voice_channel_state
|
||||
{
|
||||
STATE_NO_CHANNEL_INFO,
|
||||
STATE_ERROR,
|
||||
STATE_HUNG_UP,
|
||||
STATE_READY,
|
||||
STATE_CALL_STARTED,
|
||||
STATE_RINGING,
|
||||
STATE_CONNECTED
|
||||
} EState;
|
||||
|
||||
LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
|
||||
virtual ~LLVoiceChannel();
|
||||
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
|
||||
virtual void handleStatusChange(EStatusType status);
|
||||
virtual void handleError(EStatusType status);
|
||||
virtual void deactivate();
|
||||
virtual void activate();
|
||||
virtual void setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials);
|
||||
virtual void getChannelInfo();
|
||||
virtual BOOL isActive();
|
||||
virtual BOOL callStarted();
|
||||
|
||||
const LLUUID getSessionID() { return mSessionID; }
|
||||
EState getState() { return mState; }
|
||||
|
||||
void updateSessionID(const LLUUID& new_session_id);
|
||||
const LLSD& getNotifyArgs() { return mNotifyArgs; }
|
||||
|
||||
static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
|
||||
static LLVoiceChannel* getChannelByURI(std::string uri);
|
||||
static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
|
||||
static void initClass();
|
||||
|
||||
static void suspend();
|
||||
static void resume();
|
||||
|
||||
protected:
|
||||
virtual void setState(EState state);
|
||||
void setURI(std::string uri);
|
||||
|
||||
std::string mURI;
|
||||
std::string mCredentials;
|
||||
LLUUID mSessionID;
|
||||
EState mState;
|
||||
std::string mSessionName;
|
||||
LLSD mNotifyArgs;
|
||||
BOOL mIgnoreNextSessionLeave;
|
||||
LLHandle<LLPanel> mLoginNotificationHandle;
|
||||
|
||||
typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
|
||||
static voice_channel_map_t sVoiceChannelMap;
|
||||
|
||||
typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
|
||||
static voice_channel_map_uri_t sVoiceChannelURIMap;
|
||||
|
||||
static LLVoiceChannel* sCurrentVoiceChannel;
|
||||
static LLVoiceChannel* sSuspendedVoiceChannel;
|
||||
static BOOL sSuspended;
|
||||
};
|
||||
|
||||
class LLVoiceChannelGroup : public LLVoiceChannel
|
||||
{
|
||||
public:
|
||||
LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
|
||||
|
||||
/*virtual*/ void handleStatusChange(EStatusType status);
|
||||
/*virtual*/ void handleError(EStatusType status);
|
||||
/*virtual*/ void activate();
|
||||
/*virtual*/ void deactivate();
|
||||
/*vritual*/ void setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials);
|
||||
/*virtual*/ void getChannelInfo();
|
||||
|
||||
protected:
|
||||
virtual void setState(EState state);
|
||||
|
||||
private:
|
||||
U32 mRetries;
|
||||
BOOL mIsRetrying;
|
||||
};
|
||||
|
||||
class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
|
||||
{
|
||||
public:
|
||||
LLVoiceChannelProximal();
|
||||
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
/*virtual*/ void handleStatusChange(EStatusType status);
|
||||
/*virtual*/ void handleError(EStatusType status);
|
||||
/*virtual*/ BOOL isActive();
|
||||
/*virtual*/ void activate();
|
||||
/*virtual*/ void deactivate();
|
||||
|
||||
};
|
||||
|
||||
class LLVoiceChannelP2P : public LLVoiceChannelGroup
|
||||
{
|
||||
public:
|
||||
LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
|
||||
|
||||
/*virtual*/ void handleStatusChange(EStatusType status);
|
||||
/*virtual*/ void handleError(EStatusType status);
|
||||
/*virtual*/ void activate();
|
||||
/*virtual*/ void getChannelInfo();
|
||||
|
||||
void setSessionHandle(const std::string& handle, const std::string &inURI);
|
||||
|
||||
protected:
|
||||
virtual void setState(EState state);
|
||||
|
||||
private:
|
||||
std::string mSessionHandle;
|
||||
LLUUID mOtherUserID;
|
||||
BOOL mReceivedCall;
|
||||
};
|
||||
class LLVoiceChannel;
|
||||
|
||||
class LLFloaterIMPanel : public LLFloater
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "llviewermenu.h"
|
||||
#include "llviewermessage.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llnotify.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
|
||||
867
indra/newview/llvoicechannel.cpp
Normal file
867
indra/newview/llvoicechannel.cpp
Normal file
@@ -0,0 +1,867 @@
|
||||
/**
|
||||
* @file llvoicechannel.cpp
|
||||
* @brief Voice Channel related classes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llimview.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llvoicechannel.h"
|
||||
|
||||
extern AIHTTPTimeoutPolicy voiceCallCapResponder_timeout;
|
||||
|
||||
|
||||
LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
|
||||
LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
|
||||
LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
|
||||
LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
|
||||
|
||||
BOOL LLVoiceChannel::sSuspended = FALSE;
|
||||
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
const U32 DEFAULT_RETRIES_COUNT = 3;
|
||||
|
||||
|
||||
class LLVoiceCallCapResponder : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
public:
|
||||
LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
|
||||
|
||||
/*virtual*/ void error(U32 status, const std::string& reason); // called with bad status codes
|
||||
/*virtual*/ void result(const LLSD& content);
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return voiceCallCapResponder_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "LLVoiceCallCapResponder"; }
|
||||
|
||||
private:
|
||||
LLUUID mSessionID;
|
||||
};
|
||||
|
||||
|
||||
void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
|
||||
{
|
||||
LL_WARNS("Voice") << "LLVoiceCallCapResponder::error [status:"
|
||||
<< status << "]: " << reason << LL_ENDL;
|
||||
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
|
||||
if ( channelp )
|
||||
{
|
||||
if ( 403 == status )
|
||||
{
|
||||
//403 == no ability
|
||||
LLNotificationsUtil::add(
|
||||
"VoiceNotAllowed",
|
||||
channelp->getNotifyArgs());
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add(
|
||||
"VoiceCallGenericError",
|
||||
channelp->getNotifyArgs());
|
||||
}
|
||||
channelp->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceCallCapResponder::result(const LLSD& content)
|
||||
{
|
||||
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
|
||||
if (channelp)
|
||||
{
|
||||
// *TODO: DEBUG SPAM
|
||||
LLSD::map_const_iterator iter;
|
||||
for(iter = content.beginMap(); iter != content.endMap(); ++iter)
|
||||
{
|
||||
LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got "
|
||||
<< iter->first << LL_ENDL;
|
||||
}
|
||||
|
||||
channelp->setChannelInfo(
|
||||
content["voice_credentials"]["channel_uri"].asString(),
|
||||
content["voice_credentials"]["channel_credentials"].asString());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLVoiceChannel
|
||||
//
|
||||
LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) :
|
||||
mSessionID(session_id),
|
||||
mState(STATE_NO_CHANNEL_INFO),
|
||||
mSessionName(session_name),
|
||||
mIgnoreNextSessionLeave(FALSE)
|
||||
{
|
||||
mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
|
||||
|
||||
if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
|
||||
{
|
||||
// a voice channel already exists for this session id, so this instance will be orphaned
|
||||
// the end result should simply be the failure to make voice calls
|
||||
LL_WARNS("Voice") << "Duplicate voice channels registered for session_id " << session_id << LL_ENDL;
|
||||
}
|
||||
|
||||
LLVoiceClient::getInstance()->addObserver(this);
|
||||
}
|
||||
|
||||
LLVoiceChannel::~LLVoiceChannel()
|
||||
{
|
||||
// Must check instance exists here, the singleton MAY have already been destroyed.
|
||||
if(LLVoiceClient::instanceExists())
|
||||
{
|
||||
LLVoiceClient::getInstance()->removeObserver(this);
|
||||
}
|
||||
|
||||
sVoiceChannelMap.erase(mSessionID);
|
||||
sVoiceChannelURIMap.erase(mURI);
|
||||
}
|
||||
|
||||
void LLVoiceChannel::setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials)
|
||||
{
|
||||
setURI(uri);
|
||||
|
||||
mCredentials = credentials;
|
||||
|
||||
if (mState == STATE_NO_CHANNEL_INFO)
|
||||
{
|
||||
if (mURI.empty())
|
||||
{
|
||||
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
|
||||
LL_WARNS("Voice") << "Received empty URI for channel " << mSessionName << LL_ENDL;
|
||||
deactivate();
|
||||
}
|
||||
else if (mCredentials.empty())
|
||||
{
|
||||
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
|
||||
LL_WARNS("Voice") << "Received empty credentials for channel " << mSessionName << LL_ENDL;
|
||||
deactivate();
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(STATE_READY);
|
||||
|
||||
// if we are supposed to be active, reconnect
|
||||
// this will happen on initial connect, as we request credentials on first use
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
// just in case we got new channel info while active
|
||||
// should move over to new channel
|
||||
activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
|
||||
{
|
||||
if (channelURI != mURI)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < BEGIN_ERROR_STATUS)
|
||||
{
|
||||
handleStatusChange(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleError(type);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::handleStatusChange(EStatusType type)
|
||||
{
|
||||
// status updates
|
||||
switch(type)
|
||||
{
|
||||
case STATUS_LOGIN_RETRY:
|
||||
//mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
|
||||
LLNotificationsUtil::add("VoiceLoginRetry");
|
||||
break;
|
||||
case STATUS_LOGGED_IN:
|
||||
//if (!mLoginNotificationHandle.isDead())
|
||||
//{
|
||||
// LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
|
||||
// if (notifyp)
|
||||
// {
|
||||
// notifyp->close();
|
||||
// }
|
||||
// mLoginNotificationHandle.markDead();
|
||||
//}
|
||||
break;
|
||||
case STATUS_LEFT_CHANNEL:
|
||||
if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
|
||||
{
|
||||
// if forceably removed from channel
|
||||
// update the UI and revert to default channel
|
||||
LLNotificationsUtil::add("VoiceChannelDisconnected", mNotifyArgs);
|
||||
deactivate();
|
||||
}
|
||||
mIgnoreNextSessionLeave = FALSE;
|
||||
break;
|
||||
case STATUS_JOINING:
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_RINGING);
|
||||
}
|
||||
break;
|
||||
case STATUS_JOINED:
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_CONNECTED);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// default behavior is to just deactivate channel
|
||||
// derived classes provide specific error messages
|
||||
void LLVoiceChannel::handleError(EStatusType type)
|
||||
{
|
||||
deactivate();
|
||||
setState(STATE_ERROR);
|
||||
}
|
||||
|
||||
BOOL LLVoiceChannel::isActive()
|
||||
{
|
||||
// only considered active when currently bound channel matches what our channel
|
||||
return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
|
||||
}
|
||||
|
||||
BOOL LLVoiceChannel::callStarted()
|
||||
{
|
||||
return mState >= STATE_CALL_STARTED;
|
||||
}
|
||||
|
||||
void LLVoiceChannel::deactivate()
|
||||
{
|
||||
if (mState >= STATE_RINGING)
|
||||
{
|
||||
// ignore session leave event
|
||||
mIgnoreNextSessionLeave = TRUE;
|
||||
}
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_HUNG_UP);
|
||||
|
||||
//Default mic is OFF when leaving voice calls
|
||||
if (gSavedSettings.getBOOL("AutoDisengageMic") &&
|
||||
sCurrentVoiceChannel == this &&
|
||||
LLVoiceClient::getInstance()->getUserPTTState())
|
||||
{
|
||||
gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
// default channel is proximal channel
|
||||
sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
|
||||
sCurrentVoiceChannel->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannel::activate()
|
||||
{
|
||||
if (callStarted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// deactivate old channel and mark ourselves as the active one
|
||||
if (sCurrentVoiceChannel != this)
|
||||
{
|
||||
// mark as current before deactivating the old channel to prevent
|
||||
// activating the proximal channel between IM calls
|
||||
LLVoiceChannel* old_channel = sCurrentVoiceChannel;
|
||||
sCurrentVoiceChannel = this;
|
||||
if (old_channel)
|
||||
{
|
||||
old_channel->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
if (mState == STATE_NO_CHANNEL_INFO)
|
||||
{
|
||||
// responsible for setting status to active
|
||||
getChannelInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
setState(STATE_CALL_STARTED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLVoiceChannel::getChannelInfo()
|
||||
{
|
||||
// pretend we have everything we need
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
setState(STATE_CALL_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
|
||||
{
|
||||
voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
|
||||
if (found_it == sVoiceChannelMap.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return found_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
|
||||
{
|
||||
voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
|
||||
if (found_it == sVoiceChannelURIMap.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return found_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
LLVoiceChannel* LLVoiceChannel::getCurrentVoiceChannel()
|
||||
{
|
||||
return sCurrentVoiceChannel;
|
||||
}
|
||||
|
||||
void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
|
||||
{
|
||||
sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
|
||||
mSessionID = new_session_id;
|
||||
sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
|
||||
}
|
||||
|
||||
void LLVoiceChannel::setURI(std::string uri)
|
||||
{
|
||||
sVoiceChannelURIMap.erase(mURI);
|
||||
mURI = uri;
|
||||
sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
|
||||
}
|
||||
|
||||
void LLVoiceChannel::setState(EState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case STATE_RINGING:
|
||||
gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
|
||||
break;
|
||||
case STATE_CONNECTED:
|
||||
gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
|
||||
break;
|
||||
case STATE_HUNG_UP:
|
||||
gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mState = state;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVoiceChannel::initClass()
|
||||
{
|
||||
sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVoiceChannel::suspend()
|
||||
{
|
||||
if (!sSuspended)
|
||||
{
|
||||
sSuspendedVoiceChannel = sCurrentVoiceChannel;
|
||||
sSuspended = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVoiceChannel::resume()
|
||||
{
|
||||
if (sSuspended)
|
||||
{
|
||||
if (LLVoiceClient::getInstance()->voiceEnabled())
|
||||
{
|
||||
if (sSuspendedVoiceChannel)
|
||||
{
|
||||
sSuspendedVoiceChannel->activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVoiceChannelProximal::getInstance()->activate();
|
||||
}
|
||||
}
|
||||
sSuspended = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLVoiceChannelGroup
|
||||
//
|
||||
|
||||
LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
|
||||
LLVoiceChannel(session_id, session_name)
|
||||
{
|
||||
mRetries = DEFAULT_RETRIES_COUNT;
|
||||
mIsRetrying = FALSE;
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::deactivate()
|
||||
{
|
||||
if (callStarted())
|
||||
{
|
||||
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
|
||||
}
|
||||
LLVoiceChannel::deactivate();
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::activate()
|
||||
{
|
||||
if (callStarted()) return;
|
||||
|
||||
LLVoiceChannel::activate();
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
// we have the channel info, just need to use it now
|
||||
LLVoiceClient::getInstance()->setNonSpatialChannel(
|
||||
mURI,
|
||||
mCredentials);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::getChannelInfo()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
std::string url = region->getCapability("ChatSessionRequest");
|
||||
LLSD data;
|
||||
data["method"] = "call";
|
||||
data["session-id"] = mSessionID;
|
||||
LLHTTPClient::post(url,
|
||||
data,
|
||||
new LLVoiceCallCapResponder(mSessionID));
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials)
|
||||
{
|
||||
setURI(uri);
|
||||
|
||||
mCredentials = credentials;
|
||||
|
||||
if (mState == STATE_NO_CHANNEL_INFO)
|
||||
{
|
||||
if(!mURI.empty() && !mCredentials.empty())
|
||||
{
|
||||
setState(STATE_READY);
|
||||
|
||||
// if we are supposed to be active, reconnect
|
||||
// this will happen on initial connect, as we request credentials on first use
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
// just in case we got new channel info while active
|
||||
// should move over to new channel
|
||||
activate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//*TODO: notify user
|
||||
LL_WARNS("Voice") << "Received invalid credentials for channel " << mSessionName << LL_ENDL;
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
else if ( mIsRetrying )
|
||||
{
|
||||
// we have the channel info, just need to use it now
|
||||
LLVoiceClient::getInstance()->setNonSpatialChannel(
|
||||
mURI,
|
||||
mCredentials);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
|
||||
{
|
||||
// status updates
|
||||
switch(type)
|
||||
{
|
||||
case STATUS_JOINED:
|
||||
mRetries = 3;
|
||||
mIsRetrying = FALSE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleStatusChange(type);
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::handleError(EStatusType status)
|
||||
{
|
||||
std::string notify;
|
||||
switch(status)
|
||||
{
|
||||
case ERROR_CHANNEL_LOCKED:
|
||||
case ERROR_CHANNEL_FULL:
|
||||
notify = "VoiceChannelFull";
|
||||
break;
|
||||
case ERROR_NOT_AVAILABLE:
|
||||
//clear URI and credentials
|
||||
//set the state to be no info
|
||||
//and activate
|
||||
if ( mRetries > 0 )
|
||||
{
|
||||
mRetries--;
|
||||
mIsRetrying = TRUE;
|
||||
mIgnoreNextSessionLeave = TRUE;
|
||||
|
||||
getChannelInfo();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
notify = "VoiceChannelJoinFailed";
|
||||
mRetries = DEFAULT_RETRIES_COUNT;
|
||||
mIsRetrying = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ERROR_UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// notification
|
||||
if (!notify.empty())
|
||||
{
|
||||
LLNotificationPtr notification = LLNotificationsUtil::add(notify, mNotifyArgs);
|
||||
// echo to im window
|
||||
gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleError(status);
|
||||
}
|
||||
|
||||
void LLVoiceChannelGroup::setState(EState state)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case STATE_RINGING:
|
||||
if ( !mIsRetrying )
|
||||
{
|
||||
gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
|
||||
}
|
||||
|
||||
mState = state;
|
||||
break;
|
||||
default:
|
||||
LLVoiceChannel::setState(state);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLVoiceChannelProximal
|
||||
//
|
||||
LLVoiceChannelProximal::LLVoiceChannelProximal() :
|
||||
LLVoiceChannel(LLUUID::null, LLStringUtil::null)
|
||||
{
|
||||
activate();
|
||||
}
|
||||
|
||||
BOOL LLVoiceChannelProximal::isActive()
|
||||
{
|
||||
return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::activate()
|
||||
{
|
||||
if (callStarted()) return;
|
||||
|
||||
LLVoiceChannel::activate();
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
// this implicitly puts you back in the spatial channel
|
||||
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
|
||||
{
|
||||
if (!proximal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < BEGIN_ERROR_STATUS)
|
||||
{
|
||||
handleStatusChange(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleError(type);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
|
||||
{
|
||||
// status updates
|
||||
switch(status)
|
||||
{
|
||||
case STATUS_LEFT_CHANNEL:
|
||||
// do not notify user when leaving proximal channel
|
||||
return;
|
||||
case STATUS_VOICE_DISABLED:
|
||||
{
|
||||
gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
LLVoiceChannel::handleStatusChange(status);
|
||||
}
|
||||
|
||||
|
||||
void LLVoiceChannelProximal::handleError(EStatusType status)
|
||||
{
|
||||
std::string notify;
|
||||
switch(status)
|
||||
{
|
||||
case ERROR_CHANNEL_LOCKED:
|
||||
case ERROR_CHANNEL_FULL:
|
||||
notify = "ProximalVoiceChannelFull";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// notification
|
||||
if (!notify.empty())
|
||||
{
|
||||
LLNotificationsUtil::add(notify, mNotifyArgs);
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleError(status);
|
||||
}
|
||||
|
||||
void LLVoiceChannelProximal::deactivate()
|
||||
{
|
||||
if (callStarted())
|
||||
{
|
||||
setState(STATE_HUNG_UP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLVoiceChannelP2P
|
||||
//
|
||||
LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
|
||||
LLVoiceChannelGroup(session_id, session_name),
|
||||
mOtherUserID(other_user_id),
|
||||
mReceivedCall(FALSE)
|
||||
{
|
||||
// make sure URI reflects encoded version of other user's agent id
|
||||
// *NOTE: in case of Avaline call generated SIP URL will be incorrect.
|
||||
// But it will be overridden in LLVoiceChannelP2P::setSessionHandle() called when agent accepts call
|
||||
setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
|
||||
{
|
||||
LL_INFOS("Voice") << "P2P CALL CHANNEL STATUS CHANGE: incoming=" << int(mReceivedCall) << " newstatus=" << LLVoiceClientStatusObserver::status2string(type) << " (mState=" << mState << ")" << LL_ENDL;
|
||||
|
||||
// status updates
|
||||
switch(type)
|
||||
{
|
||||
case STATUS_LEFT_CHANNEL:
|
||||
if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
|
||||
{
|
||||
// *TODO: use it to show DECLINE voice notification
|
||||
if (mState == STATE_RINGING)
|
||||
{
|
||||
// other user declined call
|
||||
LLNotificationsUtil::add("P2PCallDeclined", mNotifyArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// other user hung up, so we didn't end the call
|
||||
LLNotificationsUtil::add("VoiceChannelDisconnectedP2P", mNotifyArgs);
|
||||
}
|
||||
deactivate();
|
||||
}
|
||||
mIgnoreNextSessionLeave = FALSE;
|
||||
return;
|
||||
case STATUS_JOINING:
|
||||
// because we join session we expect to process session leave event in the future. EXT-7371
|
||||
// may be this should be done in the LLVoiceChannel::handleStatusChange.
|
||||
mIgnoreNextSessionLeave = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleStatusChange(type);
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::handleError(EStatusType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ERROR_NOT_AVAILABLE:
|
||||
LLNotificationsUtil::add("P2PCallNoAnswer", mNotifyArgs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LLVoiceChannel::handleError(type);
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::activate()
|
||||
{
|
||||
if (callStarted()) return;
|
||||
|
||||
LLVoiceChannel::activate();
|
||||
|
||||
if (callStarted())
|
||||
{
|
||||
// no session handle yet, we're starting the call
|
||||
if (mSessionHandle.empty())
|
||||
{
|
||||
mReceivedCall = FALSE;
|
||||
LLVoiceClient::getInstance()->callUser(mOtherUserID);
|
||||
}
|
||||
// otherwise answering the call
|
||||
else
|
||||
{
|
||||
if (!LLVoiceClient::getInstance()->answerInvite(mSessionHandle))
|
||||
{
|
||||
mSessionHandle.clear();
|
||||
handleError(ERROR_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
// using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
|
||||
mSessionHandle.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::getChannelInfo()
|
||||
{
|
||||
// pretend we have everything we need, since P2P doesn't use channel info
|
||||
if (sCurrentVoiceChannel == this)
|
||||
{
|
||||
setState(STATE_CALL_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
// receiving session from other user who initiated call
|
||||
void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
|
||||
{
|
||||
BOOL needs_activate = FALSE;
|
||||
if (callStarted())
|
||||
{
|
||||
// defer to lower agent id when already active
|
||||
if (mOtherUserID < gAgent.getID())
|
||||
{
|
||||
// pretend we haven't started the call yet, so we can connect to this session instead
|
||||
deactivate();
|
||||
needs_activate = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are active and have priority, invite the other user again
|
||||
// under the assumption they will join this new session
|
||||
mSessionHandle.clear();
|
||||
LLVoiceClient::getInstance()->callUser(mOtherUserID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mSessionHandle = handle;
|
||||
|
||||
// The URI of a p2p session should always be the other end's SIP URI.
|
||||
if(!inURI.empty())
|
||||
{
|
||||
setURI(inURI);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL;
|
||||
// In the case of an incoming AvaLine call, the generated URI will be different from the
|
||||
// original one. This is because the P2P URI is based on avatar UUID but Avaline is not.
|
||||
// See LLVoiceClient::sessionAddedEvent()
|
||||
setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
|
||||
}
|
||||
|
||||
mReceivedCall = TRUE;
|
||||
|
||||
if (needs_activate)
|
||||
{
|
||||
activate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceChannelP2P::setState(EState state)
|
||||
{
|
||||
LL_INFOS("Voice") << "P2P CALL STATE CHANGE: incoming=" << int(mReceivedCall) << " oldstate=" << mState << " newstate=" << state << LL_ENDL;
|
||||
|
||||
if (mReceivedCall) // incoming call
|
||||
{
|
||||
// you only "answer" voice invites in p2p mode
|
||||
// so provide a special purpose message here
|
||||
if (mReceivedCall && state == STATE_RINGING)
|
||||
{
|
||||
gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
|
||||
mState = state;
|
||||
return;
|
||||
}
|
||||
}
|
||||
LLVoiceChannel::setState(state);
|
||||
}
|
||||
|
||||
161
indra/newview/llvoicechannel.h
Normal file
161
indra/newview/llvoicechannel.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @file llvoicechannel.h
|
||||
* @brief Voice channel related classes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_VOICECHANNEL_H
|
||||
#define LL_VOICECHANNEL_H
|
||||
|
||||
#include "llvoiceclient.h"
|
||||
|
||||
class LLVoiceChannel : public LLVoiceClientStatusObserver
|
||||
{
|
||||
public:
|
||||
typedef enum e_voice_channel_state
|
||||
{
|
||||
STATE_NO_CHANNEL_INFO,
|
||||
STATE_ERROR,
|
||||
STATE_HUNG_UP,
|
||||
STATE_READY,
|
||||
STATE_CALL_STARTED,
|
||||
STATE_RINGING,
|
||||
STATE_CONNECTED
|
||||
} EState;
|
||||
|
||||
|
||||
LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
|
||||
virtual ~LLVoiceChannel();
|
||||
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
|
||||
virtual void handleStatusChange(EStatusType status);
|
||||
virtual void handleError(EStatusType status);
|
||||
virtual void deactivate();
|
||||
virtual void activate();
|
||||
virtual void setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials);
|
||||
virtual void getChannelInfo();
|
||||
virtual BOOL isActive();
|
||||
virtual BOOL callStarted();
|
||||
|
||||
const LLUUID getSessionID() { return mSessionID; }
|
||||
EState getState() { return mState; }
|
||||
|
||||
void updateSessionID(const LLUUID& new_session_id);
|
||||
const LLSD& getNotifyArgs() { return mNotifyArgs; }
|
||||
|
||||
static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
|
||||
static LLVoiceChannel* getChannelByURI(std::string uri);
|
||||
static LLVoiceChannel* getCurrentVoiceChannel();
|
||||
|
||||
static void initClass();
|
||||
|
||||
static void suspend();
|
||||
static void resume();
|
||||
|
||||
protected:
|
||||
virtual void setState(EState state);
|
||||
void setURI(std::string uri);
|
||||
|
||||
std::string mURI;
|
||||
std::string mCredentials;
|
||||
LLUUID mSessionID;
|
||||
EState mState;
|
||||
std::string mSessionName;
|
||||
LLSD mNotifyArgs;
|
||||
BOOL mIgnoreNextSessionLeave;
|
||||
LLHandle<LLPanel> mLoginNotificationHandle;
|
||||
|
||||
typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
|
||||
static voice_channel_map_t sVoiceChannelMap;
|
||||
|
||||
typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
|
||||
static voice_channel_map_uri_t sVoiceChannelURIMap;
|
||||
|
||||
static LLVoiceChannel* sCurrentVoiceChannel;
|
||||
static LLVoiceChannel* sSuspendedVoiceChannel;
|
||||
static BOOL sSuspended;
|
||||
};
|
||||
|
||||
class LLVoiceChannelGroup : public LLVoiceChannel
|
||||
{
|
||||
public:
|
||||
LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
|
||||
|
||||
/*virtual*/ void handleStatusChange(EStatusType status);
|
||||
/*virtual*/ void handleError(EStatusType status);
|
||||
/*virtual*/ void activate();
|
||||
/*virtual*/ void deactivate();
|
||||
/*vritual*/ void setChannelInfo(
|
||||
const std::string& uri,
|
||||
const std::string& credentials);
|
||||
/*virtual*/ void getChannelInfo();
|
||||
|
||||
protected:
|
||||
virtual void setState(EState state);
|
||||
|
||||
private:
|
||||
U32 mRetries;
|
||||
BOOL mIsRetrying;
|
||||
};
|
||||
|
||||
class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
|
||||
{
|
||||
public:
|
||||
LLVoiceChannelProximal();
|
||||
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
/*virtual*/ void handleStatusChange(EStatusType status);
|
||||
/*virtual*/ void handleError(EStatusType status);
|
||||
/*virtual*/ BOOL isActive();
|
||||
/*virtual*/ void activate();
|
||||
/*virtual*/ void deactivate();
|
||||
|
||||
};
|
||||
|
||||
class LLVoiceChannelP2P : public LLVoiceChannelGroup
|
||||
{
|
||||
public:
|
||||
LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
|
||||
|
||||
/*virtual*/ void handleStatusChange(EStatusType status);
|
||||
/*virtual*/ void handleError(EStatusType status);
|
||||
/*virtual*/ void activate();
|
||||
/*virtual*/ void getChannelInfo();
|
||||
|
||||
void setSessionHandle(const std::string& handle, const std::string &inURI);
|
||||
|
||||
protected:
|
||||
virtual void setState(EState state);
|
||||
|
||||
private:
|
||||
|
||||
std::string mSessionHandle;
|
||||
LLUUID mOtherUserID;
|
||||
BOOL mReceivedCall;
|
||||
};
|
||||
|
||||
#endif // LL_VOICECHANNEL_H
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* @brief Implementation of LLVoiceClient class which is the interface to the voice client process.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
@@ -60,12 +59,12 @@
|
||||
#include "llagent.h"
|
||||
#include "llcachename.h"
|
||||
#include "llimview.h" // for LLIMMgr
|
||||
#include "llimpanel.h" // for LLVoiceChannel
|
||||
#include "llparcel.h"
|
||||
#include "llviewerparcelmgr.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llviewercamera.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llnotificationsutil.h"
|
||||
|
||||
#include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel
|
||||
|
||||
@@ -37,9 +37,8 @@
|
||||
#include "llui.h"
|
||||
#include "llbutton.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llvoiceclient.h"
|
||||
#include "llimpanel.h"
|
||||
#include "llfloateractivespeakers.h"
|
||||
#include "llfloaterchatterbox.h"
|
||||
#include "lliconctrl.h"
|
||||
|
||||
Reference in New Issue
Block a user