Fixed normal bugs EXT-4450 ([BSI] call buttons enabled when voice is disabled) and EXT-4313

(Should not be able to start a call when voice is disabled). Call buttons state now reacts on
voice changes in time.

- Added voiceWorking() method to LLVoiceClient to determine real availability of voice, because voiceEnabled()
doesn't take into account possible errors. Perhaps there is no need in two methods- some investigation will be
made and depending on its results they may become one non-static method. voiceWorking() uses state of voice
client(mState) to determine voice availability. Also some states which are not currently counted by voiceWorking()
as valid may be added if testing reveals problems.

- To enable/disable call buttons in time, LLVoiceClientStatusObserver is used. Its trigger uses states from its
enum only to skip updating button in some states(to avoid button blinking), but to determine button state
LLVoiceClient's voiceWorking() is used.

--HG--
branch : product-engine
meow-7.2.2
Andrew Dyukov 2010-01-22 22:16:57 +02:00
parent 818ab4b493
commit ab0c9c6754
15 changed files with 165 additions and 95 deletions

View File

@ -263,18 +263,9 @@ bool LLAvatarActions::isCalling(const LLUUID &id)
}
//static
bool LLAvatarActions::canCall(const LLUUID &id)
bool LLAvatarActions::canCall()
{
// For now we do not need to check whether passed UUID is ID of agent's friend.
// Use common check of Voice Client state.
{
// don't need to check online/offline status because "usual resident" (resident that is not a friend)
// can be only ONLINE. There is no way to see "usual resident" in OFFLINE status. If we see "usual
// resident" it automatically means that the resident is ONLINE. So to make a call to the "usual resident"
// we need to check only that "our" voice is enabled.
return LLVoiceClient::voiceEnabled();
}
return LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
}
// static

View File

@ -129,10 +129,10 @@ public:
static bool isCalling(const LLUUID &id);
/**
* @return true if call to the resident can be made (resident is online and voice is enabled)
* @return true if call to the resident can be made
*/
static bool canCall(const LLUUID &id);
static bool canCall();
/**
* Invite avatar to a group.
*/

View File

@ -48,6 +48,7 @@
#include "lltextutil.h"
#include "llviewercontrol.h" // for gSavedSettings
#include "llviewermenu.h" // for gMenuHolder
#include "llvoiceclient.h"
static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
S32 LLGroupListItem::sIconWidth = 0;
@ -271,6 +272,9 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
if (userdata.asString() == "activate")
return gAgent.getGroupID() != selected_group_id;
if (userdata.asString() == "call")
return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking();
return real_group_selected;
}

View File

@ -165,6 +165,8 @@ BOOL LLPanelAvatarNotes::postBuild()
resetControls();
resetData();
gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this);
return TRUE;
}
@ -337,6 +339,8 @@ LLPanelAvatarNotes::~LLPanelAvatarNotes()
if(getAvatarId().notNull())
{
LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
if(LLVoiceClient::getInstance())
LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
@ -346,6 +350,17 @@ void LLPanelAvatarNotes::changed(U32 mask)
childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId()));
}
// virtual
void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
return;
}
childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
}
void LLPanelAvatarNotes::setAvatarId(const LLUUID& id)
{
if(id.notNull())
@ -437,7 +452,6 @@ void LLPanelProfileTab::updateButtons()
bool enable_map_btn = is_avatar_online && gAgent.isGodlike() || is_agent_mappable(getAvatarId());
childSetEnabled("show_on_map_btn", enable_map_btn);
childSetEnabled("call", LLAvatarActions::canCall(getAvatarId()));
}
//////////////////////////////////////////////////////////////////////////
@ -485,6 +499,8 @@ BOOL LLPanelAvatarProfile::postBuild()
pic = getChild<LLTextureCtrl>("real_world_pic");
pic->setFallbackImageName("default_profile_picture.j2c");
gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this);
resetControls();
resetData();
@ -757,6 +773,8 @@ LLPanelAvatarProfile::~LLPanelAvatarProfile()
if(getAvatarId().notNull())
{
LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
if(LLVoiceClient::getInstance())
LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
@ -766,6 +784,17 @@ void LLPanelAvatarProfile::changed(U32 mask)
childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId()));
}
// virtual
void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
return;
}
childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
}
void LLPanelAvatarProfile::setAvatarId(const LLUUID& id)
{
if(id.notNull())

View File

@ -36,6 +36,7 @@
#include "llpanel.h"
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
#include "llvoiceclient.h"
class LLComboBox;
class LLLineEditor;
@ -122,6 +123,7 @@ private:
class LLPanelAvatarProfile
: public LLPanelProfileTab
, public LLFriendObserver
, public LLVoiceClientStatusObserver
{
public:
LLPanelAvatarProfile();
@ -134,6 +136,10 @@ public:
*/
virtual void changed(U32 mask);
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
/*virtual*/ void setAvatarId(const LLUUID& id);
/**
@ -257,6 +263,7 @@ private:
class LLPanelAvatarNotes
: public LLPanelProfileTab
, public LLFriendObserver
, public LLVoiceClientStatusObserver
{
public:
LLPanelAvatarNotes();
@ -269,6 +276,10 @@ public:
*/
virtual void changed(U32 mask);
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ BOOL postBuild();

View File

@ -101,6 +101,8 @@ LLPanelGroup::LLPanelGroup()
LLPanelGroup::~LLPanelGroup()
{
LLGroupMgr::getInstance()->removeObserver(this);
if(LLVoiceClient::getInstance())
LLVoiceClient::getInstance()->removeObserver(this);
}
void LLPanelGroup::onOpen(const LLSD& key)
@ -188,6 +190,8 @@ BOOL LLPanelGroup::postBuild()
if(panel_general)
panel_general->setupCtrls(this);
gVoiceClient->addObserver(this);
return TRUE;
}
@ -300,6 +304,17 @@ void LLPanelGroup::changed(LLGroupChange gc)
update(gc);
}
// virtual
void LLPanelGroup::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
return;
}
childSetEnabled("btn_call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
}
void LLPanelGroup::notifyObservers()
{
changed(GC_ALL);
@ -356,6 +371,13 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
(*it)->setGroupID(group_id);
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
if(gdatap)
{
childSetValue("group_name", gdatap->mName);
childSetToolTip("group_name",gdatap->mName);
}
LLButton* button_apply = findChild<LLButton>("btn_apply");
LLButton* button_refresh = findChild<LLButton>("btn_refresh");
LLButton* button_create = findChild<LLButton>("btn_create");
@ -457,17 +479,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
}
reposButtons();
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
if(gdatap)
{
childSetValue("group_name", gdatap->mName);
childSetToolTip("group_name",gdatap->mName);
//group data is already present, call update manually
update(GC_ALL);
}
}
bool LLPanelGroup::apply(LLPanelGroupTab* tab)

View File

@ -35,6 +35,7 @@
#include "llgroupmgr.h"
#include "llpanel.h"
#include "lltimer.h"
#include "llvoiceclient.h"
struct LLOfferInfo;
@ -47,7 +48,8 @@ class LLAgent;
class LLPanelGroup : public LLPanel,
public LLGroupMgrObserver
public LLGroupMgrObserver,
public LLVoiceClientStatusObserver
{
public:
LLPanelGroup();
@ -64,6 +66,10 @@ public:
// Group manager observer trigger.
virtual void changed(LLGroupChange gc);
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
void showNotice(const std::string& subject,
const std::string& message,
const bool& has_inventory,

View File

@ -64,36 +64,25 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
LLFloaterReg::showInstance("voice_controls");
}
void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
return;
}
updateCallButton();
}
void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
}
void LLPanelChatControlPanel::updateButtons(bool is_call_started)
void LLPanelChatControlPanel::updateCallButton()
{
childSetVisible("end_call_btn_panel", is_call_started);
childSetVisible("voice_ctrls_btn_panel", is_call_started);
childSetVisible("call_btn_panel", ! is_call_started);
}
LLPanelChatControlPanel::~LLPanelChatControlPanel()
{
mVoiceChannelStateChangeConnection.disconnect();
}
BOOL LLPanelChatControlPanel::postBuild()
{
childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this));
return TRUE;
}
void LLPanelChatControlPanel::draw()
{
// hide/show start call and end call buttons
bool voice_enabled = LLVoiceClient::voiceEnabled();
// hide/show call button
bool voice_enabled = LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
if (!session) return;
@ -105,8 +94,33 @@ void LLPanelChatControlPanel::draw()
&& voice_enabled
&& callback_enabled;
childSetEnabled("call_btn", enable_connect);
}
LLPanel::draw();
void LLPanelChatControlPanel::updateButtons(bool is_call_started)
{
childSetVisible("end_call_btn_panel", is_call_started);
childSetVisible("voice_ctrls_btn_panel", is_call_started);
childSetVisible("call_btn_panel", ! is_call_started);
updateCallButton();
}
LLPanelChatControlPanel::~LLPanelChatControlPanel()
{
mVoiceChannelStateChangeConnection.disconnect();
if(LLVoiceClient::getInstance())
LLVoiceClient::getInstance()->removeObserver(this);
}
BOOL LLPanelChatControlPanel::postBuild()
{
childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this));
gVoiceClient->addObserver(this);
return TRUE;
}
void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
@ -266,6 +280,8 @@ void LLPanelGroupControlPanel::draw()
// Need to resort the participant list if it's in sort by recent speaker order.
if (mParticipantList)
mParticipantList->updateRecentSpeakersOrder();
//* TODO: find better way to properly enable call button for group and remove this call from draw()
updateCallButton();
LLPanelChatControlPanel::draw();
}

View File

@ -39,7 +39,9 @@
class LLParticipantList;
class LLPanelChatControlPanel : public LLPanel
class LLPanelChatControlPanel
: public LLPanel
, public LLVoiceClientStatusObserver
{
public:
LLPanelChatControlPanel() :
@ -47,15 +49,21 @@ public:
~LLPanelChatControlPanel();
virtual BOOL postBuild();
virtual void draw();
void onCallButtonClicked();
void onEndCallButtonClicked();
void onOpenVoiceControlsClicked();
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
void updateButtons(bool is_call_started);
// Enables/disables call button depending on voice availability
void updateCallButton();
virtual void setSessionId(const LLUUID& session_id);
const LLUUID& getSessionId() { return mSessionId; }

View File

@ -462,6 +462,9 @@ LLPanelPeople::~LLPanelPeople()
delete mFriendListUpdater;
delete mRecentListUpdater;
if(LLVoiceClient::getInstance())
LLVoiceClient::getInstance()->removeObserver(this);
LLView::deleteViewByHandle(mGroupPlusMenuHandle);
LLView::deleteViewByHandle(mNearbyViewSortMenuHandle);
LLView::deleteViewByHandle(mFriendsViewSortMenuHandle);
@ -612,6 +615,8 @@ BOOL LLPanelPeople::postBuild()
if(recent_view_sort)
mRecentViewSortMenuHandle = recent_view_sort->getHandle();
gVoiceClient->addObserver(this);
// call this method in case some list is empty and buttons can be in inconsistent state
updateButtons();
@ -621,6 +626,17 @@ BOOL LLPanelPeople::postBuild()
return TRUE;
}
// virtual
void LLPanelPeople::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
return;
}
updateButtons();
}
void LLPanelPeople::updateFriendList()
{
if (!mOnlineFriendList || !mAllFriendList)
@ -775,41 +791,20 @@ void LLPanelPeople::updateButtons()
}
}
bool enable_calls = gVoiceClient->voiceWorking() && gVoiceClient->voiceEnabled();
buttonSetEnabled("teleport_btn", friends_tab_active && item_selected && isFriendOnline(selected_uuids.front()));
buttonSetEnabled("view_profile_btn", item_selected);
buttonSetEnabled("im_btn", multiple_selected); // allow starting the friends conference for multiple selection
buttonSetEnabled("call_btn", multiple_selected && canCall());
buttonSetEnabled("call_btn", multiple_selected && enable_calls);
buttonSetEnabled("share_btn", item_selected); // not implemented yet
bool none_group_selected = item_selected && selected_id.isNull();
buttonSetEnabled("group_info_btn", !none_group_selected);
buttonSetEnabled("group_call_btn", !none_group_selected);
buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls);
buttonSetEnabled("chat_btn", !none_group_selected);
}
bool LLPanelPeople::canCall()
{
std::vector<LLUUID> selected_uuids;
getCurrentItemIDs(selected_uuids);
bool result = false;
std::vector<LLUUID>::const_iterator
id = selected_uuids.begin(),
uuids_end = selected_uuids.end();
for (;id != uuids_end; ++id)
{
if (LLAvatarActions::canCall(*id))
{
result = true;
break;
}
}
return result;
}
std::string LLPanelPeople::getActiveTabName() const
{
return mTabContainer->getCurrentPanel()->getName();

View File

@ -36,13 +36,16 @@
#include <llpanel.h>
#include "llcallingcard.h" // for avatar tracker
#include "llvoiceclient.h"
class LLFilterEditor;
class LLTabContainer;
class LLAvatarList;
class LLGroupList;
class LLPanelPeople : public LLPanel
class LLPanelPeople
: public LLPanel
, public LLVoiceClientStatusObserver
{
LOG_CLASS(LLPanelPeople);
public:
@ -52,6 +55,9 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ bool notifyChildren(const LLSD& info);
// Implements LLVoiceClientStatusObserver::onChange() to enable call buttons
// when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
// internals
class Updater;
@ -73,7 +79,6 @@ private:
bool isFriendOnline(const LLUUID& id);
bool isItemsFreeOfFriends(const std::vector<LLUUID>& uuids);
bool canCall();
void updateButtons();
std::string getActiveTabName() const;

View File

@ -183,20 +183,7 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
}
else if (item == std::string("can_call"))
{
bool result = false;
std::vector<LLUUID>::const_iterator
id = mUUIDs.begin(),
uuids_end = mUUIDs.end();
for (;id != uuids_end; ++id)
{
if (LLAvatarActions::canCall(*id))
{
result = true;
break;
}
}
return result;
return LLAvatarActions::canCall();
}
return false;
}

View File

@ -628,7 +628,7 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&
}
else if (item == "can_call")
{
return LLVoiceClient::voiceEnabled();
return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking();
}
return true;

View File

@ -5853,6 +5853,11 @@ bool LLVoiceClient::voiceEnabled()
return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice");
}
bool LLVoiceClient::voiceWorking()
{
return (stateLoggedIn <= mState) && (mState <= stateLeavingSession);
}
void LLVoiceClient::setLipSyncEnabled(BOOL enabled)
{
mLipSyncEnabled = enabled;

View File

@ -191,6 +191,8 @@ static void updatePosition(void);
void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
void setVoiceEnabled(bool enabled);
static bool voiceEnabled();
// Checks is voice working judging from mState
bool voiceWorking();
void setUsePTT(bool usePTT);
void setPTTIsToggle(bool PTTIsToggle);
bool getPTTIsToggle();