From 117e22047c5752352342d64e3fb7ce00a4eb8113 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:45:04 -0500 Subject: Second Life viewer sources 1.18.1.2 --- .../indra/newview/English.lproj/InfoPlist.strings | 4 +- linden/indra/newview/Info-SecondLife.plist | 2 +- linden/indra/newview/fakevoicesoundsignal.cpp | 49 + linden/indra/newview/fakevoicesoundsignal.h | 25 + linden/indra/newview/featuretable_solaris.txt | 173 + linden/indra/newview/files.lst | 13 +- linden/indra/newview/licenses-solaris.txt | 516 +++ linden/indra/newview/linux_tools/client-readme.txt | 29 +- linden/indra/newview/linux_tools/unicode.ttf | 2 +- linden/indra/newview/linux_tools/wrapper.sh | 17 + linden/indra/newview/llagent.cpp | 62 +- linden/indra/newview/llagent.h | 2 +- linden/indra/newview/llaudiosourcevo.cpp | 2 +- linden/indra/newview/llaudiostatus.cpp | 412 -- linden/indra/newview/llaudiostatus.h | 52 - linden/indra/newview/llcallingcard.cpp | 1 + linden/indra/newview/llchatbar.cpp | 155 +- linden/indra/newview/llchatbar.h | 21 +- linden/indra/newview/llcolorswatch.cpp | 15 - linden/indra/newview/llcolorswatch.h | 2 - linden/indra/newview/llcontroldef.cpp | 604 ++- linden/indra/newview/lldebugmessagebox.cpp | 10 +- linden/indra/newview/lldebugview.cpp | 14 - linden/indra/newview/lldrawable.h | 1 + linden/indra/newview/lldrawpoolsky.h | 2 +- linden/indra/newview/lldrawpoolwater.cpp | 2 +- linden/indra/newview/llemote.h | 2 + linden/indra/newview/llface.h | 1 - linden/indra/newview/llfasttimerview.cpp | 3 +- linden/indra/newview/llfeaturemanager.cpp | 7 + linden/indra/newview/llfirstuse.cpp | 13 + linden/indra/newview/llfirstuse.h | 1 + linden/indra/newview/llfloateractivespeakers.cpp | 831 ++++ linden/indra/newview/llfloateractivespeakers.h | 211 + linden/indra/newview/llfloateranimpreview.cpp | 2 +- linden/indra/newview/llfloateravatarpicker.cpp | 7 +- linden/indra/newview/llfloaterchat.cpp | 213 +- linden/indra/newview/llfloaterchat.h | 25 +- linden/indra/newview/llfloaterchatterbox.cpp | 342 ++ linden/indra/newview/llfloaterchatterbox.h | 87 + linden/indra/newview/llfloatercustomize.cpp | 28 +- linden/indra/newview/llfloaterdirectory.cpp | 14 +- linden/indra/newview/llfloaterfriends.cpp | 395 +- linden/indra/newview/llfloaterfriends.h | 26 +- linden/indra/newview/llfloatergroups.cpp | 477 ++- linden/indra/newview/llfloatergroups.h | 79 +- linden/indra/newview/llfloaterhtmlhelp.cpp | 2 +- linden/indra/newview/llfloaterimport.cpp | 5 +- linden/indra/newview/llfloaterinspect.cpp | 19 +- linden/indra/newview/llfloaterland.cpp | 73 +- linden/indra/newview/llfloaterland.h | 2 + linden/indra/newview/llfloatermute.cpp | 1 + linden/indra/newview/llfloaternamedesc.cpp | 4 +- linden/indra/newview/llfloaternewim.cpp | 8 +- linden/indra/newview/llfloaterpostcard.cpp | 2 +- linden/indra/newview/llfloaterpreference.cpp | 10 +- linden/indra/newview/llfloaterpreference.h | 2 + linden/indra/newview/llfloaterregioninfo.cpp | 26 +- linden/indra/newview/llfloaterscriptdebug.cpp | 11 +- linden/indra/newview/llfloatersnapshot.cpp | 22 +- linden/indra/newview/llfloatertest.cpp | 7 + linden/indra/newview/llfloatertest.h | 8 + linden/indra/newview/llfloatertools.cpp | 11 +- linden/indra/newview/llfloatertools.h | 2 - linden/indra/newview/llfloatervoicewizard.cpp | 444 +++ linden/indra/newview/llfloatervoicewizard.h | 100 + linden/indra/newview/llfloaterworldmap.cpp | 75 +- linden/indra/newview/llfloaterworldmap.h | 1 + linden/indra/newview/llfolderview.cpp | 79 +- linden/indra/newview/llframestatview.cpp | 6 + linden/indra/newview/llgesturemgr.cpp | 68 +- linden/indra/newview/llgesturemgr.h | 2 +- linden/indra/newview/llglslshader.cpp | 21 +- linden/indra/newview/llhoverview.cpp | 7 + linden/indra/newview/llhudeffectlookat.cpp | 63 +- linden/indra/newview/llhudmanager.cpp | 101 - linden/indra/newview/llhudmanager.h | 10 - linden/indra/newview/llhudobject.cpp | 4 + linden/indra/newview/llhudobject.h | 3 +- linden/indra/newview/llhudtext.cpp | 3 +- linden/indra/newview/llimpanel.cpp | 1020 ++++- linden/indra/newview/llimpanel.h | 155 +- linden/indra/newview/llimview.cpp | 823 ++-- linden/indra/newview/llimview.h | 57 +- linden/indra/newview/llinventoryactions.cpp | 4 +- linden/indra/newview/llinventorybridge.cpp | 9 +- linden/indra/newview/llinventorymodel.cpp | 9 +- linden/indra/newview/llinventoryview.cpp | 12 +- linden/indra/newview/llmediaremotectrl.cpp | 167 +- linden/indra/newview/llmediaremotectrl.h | 92 +- linden/indra/newview/llmemoryview.cpp | 53 +- linden/indra/newview/llmemoryview.h | 7 + linden/indra/newview/llmutelist.cpp | 124 +- linden/indra/newview/llmutelist.h | 32 +- linden/indra/newview/llnetmap.cpp | 2 +- linden/indra/newview/llnotify.cpp | 215 +- linden/indra/newview/llnotify.h | 60 +- linden/indra/newview/lloverlaybar.cpp | 453 ++- linden/indra/newview/lloverlaybar.h | 45 +- linden/indra/newview/llpanelaudioprefs.cpp | 142 +- linden/indra/newview/llpanelaudioprefs.h | 15 +- linden/indra/newview/llpanelaudiovolume.cpp | 109 + linden/indra/newview/llpanelaudiovolume.h | 55 + linden/indra/newview/llpanelavatar.cpp | 36 +- linden/indra/newview/llpanelavatar.h | 18 +- linden/indra/newview/llpanelclassified.cpp | 21 +- linden/indra/newview/llpanelclassified.h | 25 +- linden/indra/newview/llpaneldebug.cpp | 2 + linden/indra/newview/llpaneldirbrowser.cpp | 5 +- linden/indra/newview/llpaneldisplay.cpp | 1 + linden/indra/newview/llpanelgeneral.cpp | 2 - linden/indra/newview/llpanelgroup.cpp | 11 +- linden/indra/newview/llpanelinventory.cpp | 2 +- linden/indra/newview/llpanellogin.cpp | 32 +- linden/indra/newview/llpanellogin.h | 1 + linden/indra/newview/llpanelpermissions.cpp | 16 +- linden/indra/newview/llpolymesh.cpp | 5 +- linden/indra/newview/llprefschat.cpp | 13 - linden/indra/newview/llprefsvoice.cpp | 277 ++ linden/indra/newview/llprefsvoice.h | 87 + linden/indra/newview/llpreview.cpp | 3 +- linden/indra/newview/llpreviewscript.cpp | 32 +- linden/indra/newview/llpreviewsound.cpp | 15 +- linden/indra/newview/llpreviewtexture.cpp | 2 +- linden/indra/newview/llselectmgr.cpp | 40 +- linden/indra/newview/llselectmgr.h | 5 +- linden/indra/newview/llstartup.cpp | 128 +- linden/indra/newview/llstatusbar.cpp | 110 +- linden/indra/newview/llstatusbar.h | 25 +- linden/indra/newview/lltoolbar.cpp | 35 +- linden/indra/newview/lltoolbar.h | 3 +- linden/indra/newview/lltooldraganddrop.cpp | 2 - linden/indra/newview/lltoolselect.cpp | 2 +- linden/indra/newview/lluserauth.cpp | 2 + linden/indra/newview/llviewercontrol.h | 2 + linden/indra/newview/llviewerimage.h | 22 +- linden/indra/newview/llviewerimagelist.cpp | 17 + linden/indra/newview/llviewerinventory.cpp | 6 +- linden/indra/newview/llviewerjointattachment.cpp | 17 +- linden/indra/newview/llviewerjointmesh.cpp | 215 +- linden/indra/newview/llviewerjointmesh.h | 16 + linden/indra/newview/llviewerjointmesh_sse.cpp | 114 + linden/indra/newview/llviewerjointmesh_sse2.cpp | 121 + linden/indra/newview/llviewerjointmesh_vec.cpp | 95 + linden/indra/newview/llviewermenu.cpp | 168 +- linden/indra/newview/llviewermenufile.cpp | 16 +- linden/indra/newview/llviewermessage.cpp | 98 +- linden/indra/newview/llviewerobject.cpp | 23 +- linden/indra/newview/llviewerobject.h | 5 +- linden/indra/newview/llviewerobjectlist.cpp | 6 +- linden/indra/newview/llviewerparcelmgr.cpp | 19 +- linden/indra/newview/llviewerpartsim.cpp | 2 +- linden/indra/newview/llviewerpartsource.cpp | 6 + linden/indra/newview/llviewerprecompiledheaders.h | 2 - linden/indra/newview/llviewerregion.cpp | 148 +- linden/indra/newview/llviewerregion.h | 16 +- linden/indra/newview/llviewertexteditor.cpp | 17 +- linden/indra/newview/llvieweruictrlfactory.cpp | 7 - linden/indra/newview/llvieweruictrlfactory.h | 2 - linden/indra/newview/llviewerwindow.cpp | 338 +- linden/indra/newview/llviewerwindow.h | 5 + linden/indra/newview/llvoavatar.cpp | 318 +- linden/indra/newview/llvoavatar.h | 16 + linden/indra/newview/llvocache.cpp | 45 +- linden/indra/newview/llvograss.cpp | 8 +- linden/indra/newview/llvoiceclient.cpp | 4076 ++++++++++++++++++++ linden/indra/newview/llvoiceclient.h | 523 +++ linden/indra/newview/llvoiceremotectrl.cpp | 180 + linden/indra/newview/llvoiceremotectrl.h | 56 + linden/indra/newview/llvoicevisualizer.cpp | 431 +++ linden/indra/newview/llvoicevisualizer.h | 111 + linden/indra/newview/llvolumesliderctrl.cpp | 193 - linden/indra/newview/llvolumesliderctrl.h | 56 - linden/indra/newview/llvopartgroup.cpp | 2 +- linden/indra/newview/llvosky.cpp | 8 +- linden/indra/newview/llvotree.cpp | 4 +- linden/indra/newview/llvovolume.cpp | 4 +- linden/indra/newview/llweb.cpp | 2 + linden/indra/newview/llwebbrowserctrl.cpp | 4 +- linden/indra/newview/llworldmap.cpp | 11 +- linden/indra/newview/llworldmap.h | 4 +- linden/indra/newview/llworldmapview.cpp | 3 +- linden/indra/newview/llxmlrpctransaction.cpp | 2 + .../newview/macview.xcodeproj/project.pbxproj | 238 +- linden/indra/newview/moviemaker.cpp | 10 +- linden/indra/newview/newview.vcproj | 210 +- linden/indra/newview/newview_vc8.vcproj | 208 +- linden/indra/newview/pipeline.cpp | 265 +- linden/indra/newview/pipeline.h | 27 +- linden/indra/newview/postbuild.bat | 52 +- linden/indra/newview/releasenotes.txt | 80 +- linden/indra/newview/res/newViewRes.rc | 8 +- .../newview/secondlife setup build firstlook.bat | 4 - .../newview/secondlife setup build voicebeta.bat | 4 + .../secondlife setup build voicefirstlook.bat | 4 + linden/indra/newview/skins/textures/textures.xml | 22 +- linden/indra/newview/skins/xui/de/role_actions.xml | 82 +- linden/indra/newview/skins/xui/en-us/alerts.xml | 59 +- .../newview/skins/xui/en-us/floater_about.xml | 5 +- .../newview/skins/xui/en-us/floater_about_land.xml | 78 +- .../skins/xui/en-us/floater_active_speakers.xml | 72 + .../skins/xui/en-us/floater_audio_volume.xml | 11 + .../skins/xui/en-us/floater_buy_contents.xml | 2 +- .../skins/xui/en-us/floater_chat_history.xml | 134 +- .../newview/skins/xui/en-us/floater_chatterbox.xml | 6 + .../skins/xui/en-us/floater_device_settings.xml | 4 + .../newview/skins/xui/en-us/floater_friends.xml | 225 +- .../newview/skins/xui/en-us/floater_groups.xml | 80 +- .../indra/newview/skins/xui/en-us/floater_im.xml | 39 +- .../skins/xui/en-us/floater_instant_message.xml | 57 +- .../xui/en-us/floater_instant_message_ad_hoc.xml | 119 + .../xui/en-us/floater_instant_message_group.xml | 160 + .../en-us/floater_inventory_item_properties.xml | 4 +- .../newview/skins/xui/en-us/floater_my_friends.xml | 9 + .../newview/skins/xui/en-us/floater_report_bug.xml | 4 +- .../newview/skins/xui/en-us/floater_select_key.xml | 15 + .../skins/xui/en-us/floater_settings_debug.xml | 7 +- .../indra/newview/skins/xui/en-us/floater_test.xml | 5 + .../skins/xui/en-us/floater_voice_wizard.xml | 17 + .../newview/skins/xui/en-us/menu_inventory.xml | 16 +- .../indra/newview/skins/xui/en-us/menu_viewer.xml | 70 +- linden/indra/newview/skins/xui/en-us/notify.xml | 93 +- .../indra/newview/skins/xui/en-us/panel_audio.xml | 39 + .../newview/skins/xui/en-us/panel_audio_device.xml | 77 + .../newview/skins/xui/en-us/panel_friends.xml | 62 + .../newview/skins/xui/en-us/panel_group_roles.xml | 2 + .../indra/newview/skins/xui/en-us/panel_groups.xml | 43 + .../skins/xui/en-us/panel_master_volume.xml | 13 + .../newview/skins/xui/en-us/panel_media_remote.xml | 27 +- .../newview/skins/xui/en-us/panel_music_remote.xml | 27 +- .../newview/skins/xui/en-us/panel_overlaybar.xml | 17 +- .../skins/xui/en-us/panel_preferences_audio.xml | 155 +- .../skins/xui/en-us/panel_preferences_chat.xml | 2 +- .../xui/en-us/panel_preferences_graphics3.xml | 2 +- .../skins/xui/en-us/panel_preferences_voice.xml | 89 + .../skins/xui/en-us/panel_region_estate.xml | 7 +- .../newview/skins/xui/en-us/panel_status_bar.xml | 8 +- .../newview/skins/xui/en-us/panel_toolbar.xml | 7 +- .../newview/skins/xui/en-us/panel_voice_enable.xml | 98 + .../skins/xui/en-us/panel_voice_options.xml | 46 + .../newview/skins/xui/en-us/panel_voice_remote.xml | 12 + linden/indra/newview/skins/xui/es/role_actions.xml | 372 +- linden/indra/newview/skins/xui/fr/role_actions.xml | 378 +- linden/indra/newview/skins/xui/ja/role_actions.xml | 84 +- linden/indra/newview/skins/xui/ko/role_actions.xml | 84 +- linden/indra/newview/skins/xui/pt/role_actions.xml | 372 +- linden/indra/newview/skins/xui/zh/role_actions.xml | 366 +- linden/indra/newview/viewer.cpp | 944 ++--- linden/indra/newview/viewer.h | 7 + linden/indra/newview/viewer_manifest.py | 197 +- 250 files changed, 18415 insertions(+), 5958 deletions(-) create mode 100644 linden/indra/newview/fakevoicesoundsignal.cpp create mode 100644 linden/indra/newview/fakevoicesoundsignal.h create mode 100644 linden/indra/newview/featuretable_solaris.txt create mode 100644 linden/indra/newview/licenses-solaris.txt delete mode 100644 linden/indra/newview/llaudiostatus.cpp delete mode 100644 linden/indra/newview/llaudiostatus.h create mode 100644 linden/indra/newview/llfloateractivespeakers.cpp create mode 100644 linden/indra/newview/llfloateractivespeakers.h create mode 100644 linden/indra/newview/llfloaterchatterbox.cpp create mode 100644 linden/indra/newview/llfloaterchatterbox.h create mode 100644 linden/indra/newview/llfloatervoicewizard.cpp create mode 100644 linden/indra/newview/llfloatervoicewizard.h create mode 100644 linden/indra/newview/llpanelaudiovolume.cpp create mode 100644 linden/indra/newview/llpanelaudiovolume.h create mode 100644 linden/indra/newview/llprefsvoice.cpp create mode 100644 linden/indra/newview/llprefsvoice.h create mode 100644 linden/indra/newview/llviewerjointmesh_sse.cpp create mode 100644 linden/indra/newview/llviewerjointmesh_sse2.cpp create mode 100644 linden/indra/newview/llviewerjointmesh_vec.cpp create mode 100644 linden/indra/newview/llvoiceclient.cpp create mode 100644 linden/indra/newview/llvoiceclient.h create mode 100644 linden/indra/newview/llvoiceremotectrl.cpp create mode 100644 linden/indra/newview/llvoiceremotectrl.h create mode 100644 linden/indra/newview/llvoicevisualizer.cpp create mode 100644 linden/indra/newview/llvoicevisualizer.h delete mode 100644 linden/indra/newview/llvolumesliderctrl.cpp delete mode 100644 linden/indra/newview/llvolumesliderctrl.h delete mode 100644 linden/indra/newview/secondlife setup build firstlook.bat create mode 100644 linden/indra/newview/secondlife setup build voicebeta.bat create mode 100644 linden/indra/newview/secondlife setup build voicefirstlook.bat create mode 100644 linden/indra/newview/skins/xui/en-us/floater_active_speakers.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_audio_volume.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_chatterbox.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_device_settings.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_instant_message_ad_hoc.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_instant_message_group.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_my_friends.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_select_key.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_test.xml create mode 100644 linden/indra/newview/skins/xui/en-us/floater_voice_wizard.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_audio.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_audio_device.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_friends.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_groups.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_master_volume.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_preferences_voice.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_voice_enable.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_voice_options.xml create mode 100644 linden/indra/newview/skins/xui/en-us/panel_voice_remote.xml (limited to 'linden/indra/newview') diff --git a/linden/indra/newview/English.lproj/InfoPlist.strings b/linden/indra/newview/English.lproj/InfoPlist.strings index bc1c7dd..aa9b6c0 100644 --- a/linden/indra/newview/English.lproj/InfoPlist.strings +++ b/linden/indra/newview/English.lproj/InfoPlist.strings @@ -1,5 +1,5 @@ /* Localized versions of Info.plist keys */ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 1.18.0.6"; -CFBundleGetInfoString = "Second Life version 1.18.0.6, Copyright 2004-2007 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 1.18.1.2"; +CFBundleGetInfoString = "Second Life version 1.18.1.2, Copyright 2004-2007 Linden Research, Inc."; diff --git a/linden/indra/newview/Info-SecondLife.plist b/linden/indra/newview/Info-SecondLife.plist index f4dd8e0..91d1849 100644 --- a/linden/indra/newview/Info-SecondLife.plist +++ b/linden/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ CFBundleVersion - 1.18.0.6 + 1.18.1.2 CSResourcesFileMapped diff --git a/linden/indra/newview/fakevoicesoundsignal.cpp b/linden/indra/newview/fakevoicesoundsignal.cpp new file mode 100644 index 0000000..2a271ad --- /dev/null +++ b/linden/indra/newview/fakevoicesoundsignal.cpp @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------- +// Fake Voice Sound Signal +// author: JJ Ventrella +// THIS IS A TEMPORARY FILE FOR DEVELOPMENT PURPOSES ONLY +//---------------------------------------------------------------------- + +#include "llviewerprecompiledheaders.h" +#include "fakevoicesoundsignal.h" + +//----------------------------------------------- +// constructor +//----------------------------------------------- +FakeVoiceSoundSignal::FakeVoiceSoundSignal() +{ +}//--------------------------------------------------- + + +//----------------------------------------------- +// destructor +//----------------------------------------------- +FakeVoiceSoundSignal::~FakeVoiceSoundSignal() +{ +}//--------------------------------------------------- + +//--------------------------------------------------- +F32 FakeVoiceSoundSignal::getAmplitude() +{ + return 0.0; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +bool FakeVoiceSoundSignal::getActive() +{ + return false; + +}//--------------------------------------------------- + + +//--------------------------------------------------- +void FakeVoiceSoundSignal::update() +{ + +}//--------------------------------------------------- + + + + diff --git a/linden/indra/newview/fakevoicesoundsignal.h b/linden/indra/newview/fakevoicesoundsignal.h new file mode 100644 index 0000000..9e0132c --- /dev/null +++ b/linden/indra/newview/fakevoicesoundsignal.h @@ -0,0 +1,25 @@ +//-------------------------------------------------------------------- +// Fake Voice Sound Signal +// author: JJ Ventrella +// THIS IS A TEMPORARY FILE FOR DEVELOPMENT PURPOSES ONLY +//----------------------------------------------------------------------------- +#ifndef FAKE_VOICE_SOUND_SIGNAL_H +#define FAKE_VOICE_SOUND_SIGNAL_H + +//---------------------------------------------------------------------------- +// FakeVoiceSoundSignal +//---------------------------------------------------------------------------- +class FakeVoiceSoundSignal +{ + public: + FakeVoiceSoundSignal(); + ~FakeVoiceSoundSignal(); + void update(); + F32 getAmplitude(); + bool getActive(); + +};//----------------------------------------------------------------- + // end of class +//------------------------------------------------------------------ + +#endif //FAKE_VOICE_SOUND_SIGNAL_H diff --git a/linden/indra/newview/featuretable_solaris.txt b/linden/indra/newview/featuretable_solaris.txt new file mode 100644 index 0000000..6c7acfa --- /dev/null +++ b/linden/indra/newview/featuretable_solaris.txt @@ -0,0 +1,173 @@ +version 10 + +// NOTE: This is mostly identical to featuretable.txt with a few differences +// Should be combined into one table + +// +// Generates lists of feature mask that can be applied on top of each other. +// +// // Begin comments +// list +// Starts a feature list named +// +// is the name of a feature +// is 0 or 1, whether the feature is available +// is an S32 which is the recommended value +// +// For now, the first list read sets up all of the default values +// + + +// +// All contains everything at their default settings for high end machines +// NOTE: All settings are set to the MIN of applied values, including 'all'! +// +list all +RenderVBO 1 1 +RenderAniso 1 0 +RenderAvatarMode 1 2 +RenderAvatarVP 1 1 +RenderDistance 1 128 +RenderLighting 1 1 +RenderObjectBump 1 1 +RenderParticleCount 1 4096 +RenderRippleWater 1 1 +RenderTerrainDetail 1 2 +VertexShaderEnable 1 1 + +// +// Class 0 Hardware (Unknown or just old) +// +list Class0 +VertexShaderEnable 1 0 +RenderVBO 1 0 +RenderDistance 1 64 +RenderAvatarVP 1 0 +RenderAvatarMode 1 0 +RenderLighting 1 0 +RenderObjectBump 1 0 +RenderRippleWater 1 0 + +// +// Class 1 Hardware +// +list Class1 +VertexShaderEnable 1 0 +RenderVBO 1 1 +RenderDistance 1 96 +RenderAvatarVP 1 1 +RenderAvatarMode 1 0 +RenderLighting 1 0 +RenderObjectBump 1 0 +RenderRippleWater 1 0 + +// +// Class 2 Hardware (make it purty) +// +list Class2 +VertexShaderEnable 1 1 +RenderAvatarVP 1 1 +RenderAvatarMode 1 1 +RenderLighting 1 1 +RenderObjectBump 1 1 +RenderRippleWater 1 1 + +// +// Class 3 Hardware (make it purty) +// +list Class3 +VertexShaderEnable 1 1 +RenderAvatarVP 1 1 +RenderAvatarMode 1 1 +RenderLighting 1 1 +RenderObjectBump 1 1 +RenderRippleWater 1 1 + +// +// No Pixel Shaders available +// +list NoPixelShaders +VertexShaderEnable 0 0 +RenderAvatarVP 0 0 + +// +// No Vertex Shaders available +// +list NoVertexShaders +VertexShaderEnable 0 0 +RenderAvatarVP 0 0 + +// +// "Default" setups for safe, low, medium, high +// +list safe +RenderVBO 1 0 +RenderAniso 1 0 +RenderAvatarVP 0 0 +RenderLighting 1 0 +RenderParticleCount 1 1024 +RenderTerrainDetail 1 0 + + +list low +RenderVBO 1 0 +RenderAniso 1 0 +RenderLighting 1 0 + +list medium +RenderLighting 1 0 + + +// +// CPU based feature masks +// + +// 1Ghz or less (equiv) +list CPUSlow +RenderParticleCount 1 1024 + + +// +// RAM based feature masks +// +list RAM256MB +RenderObjectBump 0 0 + + +// +// Graphics card based feature masks +// +list OpenGLPre15 +RenderVBO 1 0 + +list Intel +RenderVBO 1 0 +RenderAniso 1 0 +RenderLighting 1 0 +RenderTerrainDetail 1 0 + +list GeForce2 +RenderVBO 1 1 +RenderAniso 1 0 +RenderLighting 1 0 +RenderParticleCount 1 2048 +RenderTerrainDetail 1 0 + +list GeForce3 + +list ATI + +list Radeon8500 +RenderLighting 1 0 +RenderParticleCount 1 4096 + +// Hacked to be paranoid "safe" +list Radeon9700 +RenderParticleCount 1 4096 + +// Hacked to be paranoid "safe" +list MobilityRadeon9000 +RenderLighting 1 0 +RenderParticleCount 1 4096 + +list GeForceFX diff --git a/linden/indra/newview/files.lst b/linden/indra/newview/files.lst index 6c51893..a5c348c 100644 --- a/linden/indra/newview/files.lst +++ b/linden/indra/newview/files.lst @@ -6,7 +6,6 @@ newview/llanimalcontrols.cpp newview/llassetuploadresponders.cpp newview/llasynchostbyname.cpp newview/llaudiosourcevo.cpp -newview/llaudiostatus.cpp newview/llbbox.cpp newview/llbox.cpp newview/llcallbacklist.cpp @@ -56,6 +55,7 @@ newview/llfilepicker.cpp newview/llfirstuse.cpp newview/llflexibleobject.cpp newview/llfloaterabout.cpp +newview/llfloateractivespeakers.cpp newview/llfloateranimpreview.cpp newview/llfloaterauction.cpp newview/llfloateravatarinfo.cpp @@ -68,6 +68,7 @@ newview/llfloaterbuy.cpp newview/llfloaterbuycurrency.cpp newview/llfloaterbuyland.cpp newview/llfloaterchat.cpp +newview/llfloaterchatterbox.cpp newview/llfloaterclothing.cpp newview/llfloatercolorpicker.cpp newview/llfloatercustomize.cpp @@ -107,6 +108,7 @@ newview/llfloatertest.cpp newview/llfloatertools.cpp newview/llfloatertopobjects.cpp newview/llfloatertos.cpp +newview/llfloatervoicewizard.cpp newview/llfloaterworldmap.cpp newview/llfolderview.cpp newview/llfollowcam.cpp @@ -162,6 +164,7 @@ newview/llnetmap.cpp newview/llnotify.cpp newview/lloverlaybar.cpp newview/llpanelaudioprefs.cpp +newview/llpanelaudiovolume.cpp newview/llpanelavatar.cpp newview/llpanelclassified.cpp newview/llpanelcontents.cpp @@ -206,6 +209,7 @@ newview/llpolymesh.cpp newview/llpolymorph.cpp newview/llprefschat.cpp newview/llprefsim.cpp +newview/llprefsvoice.cpp newview/llpreviewanim.cpp newview/llpreview.cpp newview/llpreviewgesture.cpp @@ -275,6 +279,9 @@ newview/llviewerinventory.cpp newview/llviewerjointattachment.cpp newview/llviewerjoint.cpp newview/llviewerjointmesh.cpp +newview/llviewerjointmesh_sse.cpp +newview/llviewerjointmesh_sse2.cpp +newview/llviewerjointmesh_vec.cpp newview/llviewerjointshape.cpp newview/llviewerjoystick.cpp newview/llviewerkeyboard.cpp @@ -305,8 +312,10 @@ newview/llvocache.cpp newview/llvoclouds.cpp newview/llvograss.cpp newview/llvoground.cpp +newview/llvoiceclient.cpp +newview/llvoiceremotectrl.cpp +newview/llvoicevisualizer.cpp newview/llvoinventorylistener.cpp -newview/llvolumesliderctrl.cpp newview/llvopartgroup.cpp newview/llvosky.cpp newview/llvostars.cpp diff --git a/linden/indra/newview/licenses-solaris.txt b/linden/indra/newview/licenses-solaris.txt new file mode 100644 index 0000000..a0dc048 --- /dev/null +++ b/linden/indra/newview/licenses-solaris.txt @@ -0,0 +1,516 @@ +=========== +APR License +=========== + +Copyright 2000-2004 The Apache Software Foundation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +============== +Base32 License +============== + + * Copyright (c) 2006 Christian Biere + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the authors nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + +========== +Cg License +========== + +Copyright (c) 2002, NVIDIA Corporation. + + + +NVIDIA Corporation("NVIDIA") supplies this software to you in consideration +of your agreement to the following terms, and your use, installation, +modification or redistribution of this NVIDIA software constitutes +acceptance of these terms. If you do not agree with these terms, please do +not use, install, modify or redistribute this NVIDIA software. + + + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive license, +under NVIDIA's copyrights in this original NVIDIA software (the "NVIDIA +Software"), to use, reproduce, modify and redistribute the NVIDIA +Software, with or without modifications, in source and/or binary forms; +provided that if you redistribute the NVIDIA Software, you must retain the +copyright notice of NVIDIA, this notice and the following text and +disclaimers in all such redistributions of the NVIDIA Software. Neither the +name, trademarks, service marks nor logos of NVIDIA Corporation may be used +to endorse or promote products derived from the NVIDIA Software without +specific prior written permission from NVIDIA. Except as expressly stated +in this notice, no other rights or licenses express or implied, are granted +by NVIDIA herein, including but not limited to any patent rights that may be +infringed by your derivative works or by other works in which the NVIDIA +Software may be incorporated. No hardware is licensed hereunder. + + + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING +WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR ITS USE AND OPERATION +EITHER ALONE OR IN COMBINATION WITH OTHER PRODUCTS. + + + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, +EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOST +PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY OUT OF THE USE, +REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE NVIDIA SOFTWARE, +HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING +NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF NVIDIA HAS BEEN ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + + +============ +cURL License +============ + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2002, Daniel Stenberg, . + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. + + +============= +expat License +============= + +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +================ +FreeType License +================ + +Portions of this software are copyright (c) 2003 The FreeType +Project (www.freetype.org). All rights reserved. + +========================== +FSI FontShop International +========================== + +Certain of the fonts in the Meta family of copyrighted typefaces are +used in Second Life under license from FSI FontShop +International. Copies of such Meta fonts that are included in the +Viewer are not themselves open source and are not available under the +GPL license, and they may not be copied. Developers may use those +fonts solely to the extent necessary to use or customize the Linden +Software in Second Life and to develop and distribute content solely +for use in the Second Life environment, and for no other purposes. +Second Life developers who wish to make other uses of Meta fonts must +obtain a license from FSI FontShop International at www.fontfont.com. + +========== +GL License +========== + +Mesa 3-D graphics library +Version: 6.2 + +Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +======================= +JPEG Library 6b License +======================= + +This software is based in part on the work of the Independent JPEG Group + +================ +JPEG2000 License +================ + +Copyright 2001, David Taubman, The University of New South Wales (UNSW) +The copyright owner is Unisearch Ltd, Australia (commercial arm of UNSW) +Neither this copyright statement, nor the licensing details below +may be removed from this file or dissociated from its contents. + +Licensee: Linden Research, Inc. +License number: 00024 +The licensee has been granted a COMMERCIAL license to the contents of +this source file. A brief summary of this license appears below. This +summary is not to be relied upon in preference to the full text of the +license agreement, accepted at purchase of the license. +1. The Licensee has the right to Commercial Use of the Kakadu software, + including distribution of one or more Applications built using the + software. +2. The Licensee has the right to Internal Use of the Kakadu software, + including use by employees of the Licensee or an Affiliate for the + purpose of performing services on behalf of the Licensee or Affiliate, + or in the performance of services for Third Parties who engage Licensee + or an Affiliate for such services. +3. The Licensee has the right to distribute Reusable Code (including + source code and dynamically or statically linked libraries) to a Third + Party, provided the Third Party possesses a license to use the Kakadu + software. + +================== +ogg/vorbis License +================== + +Copyright (c) 2001, Xiphophorus + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiphophorus nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +=========== +SDL License +=========== + +SDL - Simple DirectMedia Layer +Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Sam Lantinga +slouken@libsdl.org + +The GNU Library GPL is available at http://www.gnu.org/copyleft/lesser.html + +============= +ELFIO License +============= + +ELFIO.h - ELF reader and producer. +Copyright (C) 2001 Serge Lamikhov-Center + +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; either +version 2.1 of the License, or (at your option) any later version. + +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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +The GNU Library GPL is available at http://www.gnu.org/copyleft/lesser.html + +=============== +OpenSSL License +=============== + +Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + +4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + endorse or promote products derived from this software without + prior written permission. For written permission, please contact + openssl-core@openssl.org. + +5. Products derived from this software may not be called "OpenSSL" + nor may "OpenSSL" appear in their names without prior written + permission of the OpenSSL Project. + +6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit (http://www.openssl.org/)" + +THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. +==================================================================== + +This product includes cryptographic software written by Eric Young +(eay@cryptsoft.com). This product includes software written by Tim +Hudson (tjh@cryptsoft.com). + + + +======================= +Original SSLeay License +======================= + +Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) +All rights reserved. + +This package is an SSL implementation written +by Eric Young (eay@cryptsoft.com). +The implementation was written so as to conform with Netscapes SSL. + +This library is free for commercial and non-commercial use as long as +the following conditions are aheared to. The following conditions +apply to all code found in this distribution, be it the RC4, RSA, +lhash, DES, etc., code; not just the SSL code. The SSL documentation +included with this distribution is covered by the same copyright terms +except that the holder is Tim Hudson (tjh@cryptsoft.com). + +Copyright remains Eric Young's, and as such any Copyright notices in +the code are not to be removed. +If this package is used in a product, Eric Young should be given attribution +as the author of the parts of the library used. +This can be in the form of a textual message at program startup or +in documentation (online or textual) provided with the package. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + "This product includes cryptographic software written by + Eric Young (eay@cryptsoft.com)" + The word 'cryptographic' can be left out if the rouines from the library + being used are not cryptographic related :-). +4. If you include any Windows specific code (or a derivative thereof) from + the apps directory (application code) you must include an acknowledgement: + "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + +THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +The licence and distribution terms for any publically available version or +derivative of this code cannot be changed. i.e. this code cannot simply be +copied and put under another distribution licence +[including the GNU Public Licence.] + + +================== +xmlrpc-epi License +================== + +Copyright 2000 Epinions, Inc. + +Subject to the following 3 conditions, Epinions, Inc. permits you, free of charge, to (a) use, copy, distribute, modify, perform and display this software and associated documentation files (the "Software"), and (b) permit others to whom the Software is furnished to do so as well. + +1) The above copyright notice and this permission notice shall be included without modification in all copies or substantial portions of the Software. + +2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + +3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. + + +=============== +libuuid License +=============== + +Copyright (C) 1999, 2000, 2003, 2004 by Theodore Ts'o + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF +WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + +============ +zlib License +============ + +'zlib' general purpose compression library version 1.1.4, March 11th, 2002 + +Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +The origin of this software must not be misrepresented; you must not claim +that you wrote the original software. If you use this software in a product, +an acknowledgment in the product documentation would be appreciated but is +not required. + +Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly +jloup@gzip.org + +Mark Adler +madler@alumni.caltech.edu diff --git a/linden/indra/newview/linux_tools/client-readme.txt b/linden/indra/newview/linux_tools/client-readme.txt index 63086c8..e07384c 100644 --- a/linden/indra/newview/linux_tools/client-readme.txt +++ b/linden/indra/newview/linux_tools/client-readme.txt @@ -15,6 +15,7 @@ Life itself - please see . 5.3. 'Shiny' and client performance 5.4. Audio 5.5. 'Alt' key for camera controls doesn't work + 5.6. In-world movie playback 6. Advanced Troubleshooting 6.1. Audio 6.2. OpenGL @@ -57,6 +58,7 @@ Minimum requirements: * Video/Graphics Card: o nVidia GeForce 2, GeForce 4mx, or better o OR ATI Radeon 8500, 9250, or better + (nVidia cards are strongly recommended for the Linux client) **NOTE**: Second Life absolutely requires you to have recent, correctly- configured OpenGL 3D drivers for your hardware - the graphics drivers @@ -76,6 +78,14 @@ unpacked it into - no installation step is required. Run ./secondlife from the installation directory to start Second Life. +For in-world MOVIE PLAYBACK, you will need GStreamer 0.10 installed on your +system. This is optional - it is not required for general client +functionality. If you have GStreamer 0.10 installed, the selection of +in-world movies you can successfully play will depend on the GStreamer +plugins you have; if you cannot play a certain in-world movie then you are +probably missing the appropriate GStreamer plugin on your system - you may +be able to install it (see TROUBLESHOOTING). + User data is stored in the hidden directory ~/.secondlife by default; you may override this location with the SECONDLIFE_USER_DIR environment variable if you wish. @@ -93,10 +103,9 @@ the Alpha release of the Linux client. stability. See PROBLEM 3 in the TROUBLESHOOTING section if you wish to turn these on to possibly enhance your experience. -* MISC - The following user-visible features are not currently fully - implemented on the Linux client and are therefore known not to work properly - at this time: - * QuickTime movie playback and movie recording +* MISC - The following features are not currently fully implemented on the + Linux client and are therefore known not to work properly: + * Movie recording * Full Unicode font rendering * Auto-updater @@ -176,6 +185,13 @@ SOLUTION:- Some window managers eat the Alt key for their own purposes; you example, the 'Windows' key!) which will allow the Alt key to function properly with mouse actions in Second Life and other applications. +PROBLEM 6:- In-world movie playback doesn't work for me. +SOLUTION:- You need to have a working installation of GStreamer 0.10; this + is usually an optional package for most versions of Linux. If you have + installed GStreamer 0.10 and you can play some movies but not others then + you need to install a wider selection of GStreamer plugins, either + from your vendor or an appropriate third party. + 6. ADVANCED TROUBLESHOOTING -=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -219,9 +235,8 @@ For problems and discussion concerning unofficial (not secondlife.com) releases, please contact your packager or the SLDev mailing list: -In-world help: Please use the 'Help' menu in the client for general -non-Linux-specific Second Life help including live support from the fabulous -'Help Request' team. +In-world help: Please use the 'Help' menu in the client for various +non-Linux-specific Second Life help options. In-world discussion: There is a 'Linux Client Users' group inside Second Life which is free to join. You can find it by pressing diff --git a/linden/indra/newview/linux_tools/unicode.ttf b/linden/indra/newview/linux_tools/unicode.ttf index c9c230d..91e6150 120000 --- a/linden/indra/newview/linux_tools/unicode.ttf +++ b/linden/indra/newview/linux_tools/unicode.ttf @@ -1 +1 @@ -/usr/share/fonts/truetype/kochi/kochi-mincho.ttf \ No newline at end of file +/usr/share/fonts/truetype/kochi/kochi-gothic.ttf \ No newline at end of file diff --git a/linden/indra/newview/linux_tools/wrapper.sh b/linden/indra/newview/linux_tools/wrapper.sh index d77da88..d39fc3a 100755 --- a/linden/indra/newview/linux_tools/wrapper.sh +++ b/linden/indra/newview/linux_tools/wrapper.sh @@ -48,6 +48,23 @@ export SDL_VIDEO_X11_DGAMOUSE=0 RUN_PATH=`dirname "$0" || echo .` cd "${RUN_PATH}" +if [ -n "$LL_TCMALLOC" ]; then + tcmalloc_libs='/usr/lib/libtcmalloc.so.0 /usr/lib/libstacktrace.so.0 /lib/libpthread.so.0' + all=1 + for f in $tcmalloc_libs; do + if [ ! -f $f ]; then + all=0 + fi + done + if [ $all != 1 ]; then + echo 'Cannot use tcmalloc libraries: components missing' 1>&2 + else + export LD_PRELOAD=$(echo $tcmalloc_libs | tr ' ' :) + if [ -z "$HEAPCHECK" -a -z "$HEAPPROFILE" ]; then + export HEAPCHECK=${HEAPCHECK:-normal} + fi + fi +fi LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}" $LL_WRAPPER bin/do-not-directly-run-secondlife-bin `cat gridargs.dat` $@ | cat echo diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp index 307ab6f..3f6ab4f 100644 --- a/linden/indra/newview/llagent.cpp +++ b/linden/indra/newview/llagent.cpp @@ -61,6 +61,7 @@ #include "llface.h" #include "llfirstuse.h" #include "llfloater.h" +#include "llfloateractivespeakers.h" #include "llfloateravatarinfo.h" #include "llfloaterbuildoptions.h" #include "llfloaterchat.h" @@ -117,6 +118,7 @@ #include "pipeline.h" #include "roles_constants.h" #include "viewer.h" +#include "llvoiceclient.h" // Ventrella #include "llfollowcam.h" @@ -346,7 +348,7 @@ LLAgent::LLAgent() mEffectColor(0.f, 1.f, 1.f, 1.f), mHaveHomePosition(FALSE), mHomeRegionHandle( 0 ), - mNearChatRadius(10.f), + mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f), mGodLevel( GOD_NOT ), @@ -2844,7 +2846,7 @@ void LLAgent::endAnimationUpdateUI() gMorphView->setVisible(FALSE); } - gIMView->setFloaterOpen( FALSE ); + gIMMgr->setFloaterOpen( FALSE ); gConsole->setVisible( TRUE ); if (mAvatarObject) @@ -3259,6 +3261,19 @@ void LLAgent::updateCamera() setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); } + // Send the camera position to the spatialized voice system. + if(gVoiceClient && getRegion()) + { + LLMatrix3 rot; + rot.setRows(gCamera->getAtAxis(), gCamera->getLeftAxis (), gCamera->getUpAxis()); + + // MBW -- XXX -- Setting velocity to 0 for now. May figure it out later... + gVoiceClient->setCameraPosition( + getRegion()->getPosGlobalFromRegion(gCamera->getOrigin()),// position + LLVector3::zero, // velocity + rot); // rotation matrix + } + // update the travel distance stat // this isn't directly related to the camera // but this seemed like the best place to do this @@ -3269,7 +3284,7 @@ void LLAgent::updateCamera() mDistanceTraveled += delta.magVec(); } mLastPositionGlobal = global_pos; - + if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook()) { LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + @@ -4465,18 +4480,23 @@ void LLAgent::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) //----------------------------------------------------------------------------- // heardChat() //----------------------------------------------------------------------------- -void LLAgent::heardChat(const LLChat& chat) +void LLAgent::heardChat(const LLUUID& id) { - if (chat.mChatType == CHAT_TYPE_START - || chat.mChatType == CHAT_TYPE_STOP) + // log text and voice chat to speaker mgr + // for keeping track of active speakers, etc. + gLocalSpeakerMgr->speakerChatted(id); + + // don't respond to your own voice + if (id == getID()) return; + + if (ll_rand(2) == 0) { - return; - } + LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); + setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero); + } - mLastChatterID = chat.mFromID; + mLastChatterID = id; mChatTimer.reset(); - - mNearChatRadius = CHAT_NORMAL_RADIUS / 2.f; } //----------------------------------------------------------------------------- @@ -5068,14 +5088,6 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global) void update_group_floaters(const LLUUID& group_id) { - // *HACK: added to do a live update of the groups floater if it is - // open. - LLFloaterGroups* fg = LLFloaterGroups::getInstance(gAgent.getID()); - if(fg) - { - fg->reset(); - } - LLFloaterGroupInfo::refreshGroup(group_id); // update avatar info @@ -5085,10 +5097,10 @@ void update_group_floaters(const LLUUID& group_id) fa->resetGroupList(); } - if (gIMView) + if (gIMMgr) { // update the talk view - gIMView->refresh(); + gIMMgr->refresh(); } } @@ -5179,6 +5191,7 @@ void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) if (need_floater_update) { update_group_floaters(group.mID); + gAgent.fireEvent(new LLEvent(&gAgent, "new group"), ""); } } @@ -5508,6 +5521,11 @@ bool LLAgent::teleportCore(bool is_local) gAgent.setTeleportState( LLAgent::TELEPORT_START ); } make_ui_sound("UISndTeleportOut"); + + // MBW -- Let the voice client know a teleport has begun so it can leave the existing channel. + // This was breaking the case of teleporting within a single sim. Backing it out for now. +// gVoiceClient->leaveChannel(); + return true; } @@ -6770,7 +6788,7 @@ void LLAgent::removeWearable( EWearableType type ) if( old_wearable->isDirty() ) { // Bring up view-modal dialog: Save changes? Yes, No, Cancel - gViewerWindow->alertXml("WearableSave", LLAgent::onRemoveWearableDialog, (void*)(S32)type ); + gViewerWindow->alertXml("WearableSave", LLAgent::onRemoveWearableDialog, (void*)type ); return; } else diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h index e4d207c..7fb4571 100644 --- a/linden/indra/newview/llagent.h +++ b/linden/indra/newview/llagent.h @@ -190,7 +190,7 @@ public: void setObjectTracking(BOOL track) { mTrackFocusObject = track; } // void setLookingAtAvatar(BOOL looking); - void heardChat(const LLChat& chat); + void heardChat(const LLUUID& id); void lookAtLastChat(); LLUUID getLastChatter() { return mLastChatterID; } F32 getTypingTime() { return mTypingTimer.getElapsedTimeF32(); } diff --git a/linden/indra/newview/llaudiosourcevo.cpp b/linden/indra/newview/llaudiosourcevo.cpp index 084d532..b0e0758 100644 --- a/linden/indra/newview/llaudiosourcevo.cpp +++ b/linden/indra/newview/llaudiosourcevo.cpp @@ -83,7 +83,7 @@ void LLAudioSourceVO::updateGain() { mute = TRUE; } - else if (gMuteListp->isMuted(mOwnerID)) + else if (gMuteListp->isMuted(mOwnerID, LLMute::flagObjectSounds)) { mute = TRUE; } diff --git a/linden/indra/newview/llaudiostatus.cpp b/linden/indra/newview/llaudiostatus.cpp deleted file mode 100644 index f24d939..0000000 --- a/linden/indra/newview/llaudiostatus.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/** - * @file llaudiostatus.cpp - * @brief Audio channel allocation information - * - * Copyright (c) 2001-2007, 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 - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "llviewerprecompiledheaders.h" - -#include "llaudiostatus.h" - -#include "linked_lists.h" -#include "llmath.h" // clampf() -#include "llgl.h" -#include "llview.h" -#include "llfontgl.h" -#include "llcircuit.h" -#include "message.h" -#include "sound_ids.h" -#include "audioengine.h" - -#include "llui.h" -#include "llagent.h" -#include "llviewercontrol.h" -#include "viewer.h" - -#include "llglheaders.h" - -// -// Imported globals -// -extern LLMessageSystem* gMessageSystem; -extern LLAudioEngine* gAudiop; - -// -// Constants -// - - -LLAudiostatus::LLAudiostatus(const std::string& name, const LLRect& rect) - : LLView(name, rect, FALSE) -{ - mPage = 0; -} - -// -// Functions -// - -EWidgetType LLAudiostatus::getWidgetType() const -{ - return WIDGET_TYPE_AUDIO_STATUS; -} - -LLString LLAudiostatus::getWidgetTag() const -{ - return LL_AUDIOSTATUS_TAG; -} - -const F32 AUDIOSTATUS_SIZE = 64; - -void LLAudiostatus::draw() -{ - /* - mPage = gSavedSettings.getS32("AudioInfoPage"); - - if (!getVisible() || !mPage) - { - return; - } - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - // We're going to be drawing flat shaded rectangles - { - LLGLSNoTexture gls_ui_no_texture; - - // Draw background black rectangle - glColor4f(0.f, 0.f, 0.f, 0.3f); - gl_rect_2d(0, 0, 325, -340); // -y is down (don't know why) - } - - glPopMatrix(); - glPushMatrix(); - - S32 channel; - char out_str[64]; - LLColor4 color; - - if (gAudiop) - { - for (channel = 0; channel < MAX_BUFFERS; channel++) - { - if (gAudiop->getFlags(channel) & LL_SOUND_FLAG_LOOP) - { - color.setVec(0.5f,0.5f,1.f,1.f); - } - else - { - color.setVec(1.f,1.f,1.f,1.f); - } - - sprintf(out_str,"%d:",channel); - - U8 render_style = LLFontGL::NORMAL; - - if (gAudiop->getFlags(channel) & LL_SOUND_FLAG_SYNC_MASTER) - { - render_style |= LLFontGL::BOLD; - } - - if (gAudiop->getFlags(channel) & LL_SOUND_FLAG_SYNC_SLAVE) - { - render_style |= LLFontGL::ITALIC; - } - - if (gAudiop->getFlags(channel) & LL_SOUND_FLAG_SYNC_PENDING) - { - render_style |= LLFontGL::UNDERLINE; - } - - LLFontGL::sMonospace->render(out_str, 0, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP, render_style, S32_MAX, S32_MAX, NULL); - -// render_style = LLFontGL::NORMAL; -// if (gAudiop->mCurrentSyncMaster == channel) -// { -// render_style |= LLFontGL::BOLD; -// } - - if (!gAudiop->mBufferInUse[channel]) - { - color.setVec(0.5f,0.5f,0.5f,1.f); - } - else if (gAudiop->isPlaying(channel)) - { - color.setVec(0.f,1.f,0.f,1.f); - } - else - { - color.setVec(1.f,0.f,0.f,1.f); - } - - if (gAudiop->mWindBufferID ==channel) - { - strcpy(out_str,"wind DMO"); - } - else if (gAudiop->mWaterBufferID ==channel) - { - strcpy(out_str,"water DMO"); - } - else if (gAudiop->mGUID[channel] == SND_CHIRP) - { - strcpy(out_str,"chirp"); - } - else if (gAudiop->mGUID[channel] == SND_SHOT) - { - strcpy(out_str,"shot"); - } - else if (gAudiop->mGUID[channel] == SND_MORTAR) - { - strcpy(out_str,"mortar"); - } - else if (gAudiop->mGUID[channel] == SND_HIT) - { - strcpy(out_str,"hit"); - } - else if (gAudiop->mGUID[channel] == SND_EXPLOSION) - { - strcpy(out_str,"explosion"); - } - else if (gAudiop->mGUID[channel] == SND_BOING) - { - strcpy(out_str,"boing"); - } - else if (gAudiop->mGUID[channel] == SND_MUNCH) - { - strcpy(out_str,"munch"); - } - else if (gAudiop->mGUID[channel] == SND_PUNCH) - { - strcpy(out_str,"punch"); - } - else if (gAudiop->mGUID[channel] == SND_SPLASH) - { - strcpy(out_str,"splash"); - } - else if (gAudiop->mGUID[channel] == SND_CLICK) - { - strcpy(out_str,"click"); - } - else if (gAudiop->mGUID[channel] == SND_ARROW_SHOT) - { - strcpy(out_str,"arrow"); - } - else if (gAudiop->mGUID[channel] == SND_ARROW_THUD) - { - strcpy(out_str,"arrow thud"); - } - else if (gAudiop->mGUID[channel] == SND_SILENCE) - { - strcpy(out_str,"silence"); - } - else if (gAudiop->mGUID[channel] == SND_WELCOME) - { - strcpy(out_str,"welcome"); - } - else if (gAudiop->mGUID[channel] == SND_WELCOME) - { - strcpy(out_str,"welcome"); - } - else if (gAudiop->mGUID[channel] == SND_READY_FOR_BATTLE) - { - strcpy(out_str,"ready for battle"); - } - else if (gAudiop->mGUID[channel] == SND_SQUISH) - { - strcpy(out_str,"squish"); - } - else if (gAudiop->mGUID[channel] == SND_FOOTSTEPS) - { - strcpy(out_str,"footsteps"); - } - else if (gAudiop->mGUID[channel] == SND_BALL_COLLISION) - { - strcpy(out_str,"ball collision"); - } - else - { - gAudiop->mGUID[channel].toString(out_str); - } - - out_str[8] = 0; - LLFontGL::sMonospace->render(out_str, 23, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP, render_style, S32_MAX, S32_MAX, NULL); - - if (mPage == 1) - { - LLVector3 pos = gAudiop->getSourcePos(channel); - sprintf(out_str,"%6.2f %6.2f %6.2f",pos.mV[VX],pos.mV[VY],pos.mV[VZ]); - LLFontGL::sMonospace->render(out_str, 103, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - - F32 gain = gAudiop->getSourceGain_dB(channel); - sprintf(out_str,"%7.2f",gain); - LLFontGL::sMonospace->render(out_str, 260, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - - sprintf(out_str,"%X", gAudiop->mPriority[channel] >> 28); - LLFontGL::sMonospace->render(out_str, 315, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - } - else if (mPage == 4) - { - F32 indicator_width = 240; - - glPushMatrix(); - // We're going to be drawing flat shaded rectangles - LLGLSNoTexture gls_no_texture; - // Draw background black rectangle - glColor4f(0.f, 0.f, 0.f, 1.0f); - - F32 length = gAudiop->getSourceLength(channel); - length = length/(44100.0*2.0); // length in seconds - length = length/10.f; // rescale per maximum length - - gl_rect_2d(80, (-channel*10)-1, 80 + llfloor((F32)(indicator_width * length)), (-channel*10)-9); // -y is down (don't know why) - - F32 current_pointer = gAudiop->getSourceCurrentSample(channel); - current_pointer = current_pointer/(44100.0*2.0); // length in seconds - current_pointer = current_pointer/10.f; // rescale per maximum length - - if (!gAudiop->mBufferInUse[channel]) - { - glColor4f(0.5f,0.5f,0.5f,1.f); - } - else if (gAudiop->isPlaying(channel)) - { - glColor4f(0.f,1.f,0.f,1.f); - } - else - { - glColor4f(1.f,0.f,0.f,1.f); - } - - gl_rect_2d(80, (-channel*10)-1, 80 + llfloor((F32)(indicator_width * current_pointer)), (-channel*10)-9); // -y is down (don't know why) - - glPopMatrix(); - { - LLGLSUIDefault gls_ui; - - color.setVec(1.f,1.f,1.f,1.f); - - sprintf(out_str,"%6.3f",length*10.f); - LLFontGL::sMonospace->render(out_str, 200, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP, render_style, S32_MAX, S32_MAX, NULL); - - if (!(gAudiop->mVO_ID[channel].isNull())) - { - gAudiop->mVO_ID[channel].toString(out_str); - out_str[8] = 0; - LLFontGL::sMonospace->render(out_str, 260, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP, render_style, S32_MAX, S32_MAX, NULL); - } - if (gAudiop->mQueuedTrigger[channel]) - { - gAudiop->mQueuedTrigger[channel]->mID.toString(out_str); - out_str[8] = 0; - LLFontGL::sMonospace->render(out_str, 320, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP, render_style, S32_MAX, S32_MAX, NULL); - } - } - } - else - { - S32 volume; - S32 freq; - S32 inside; - S32 outside; - LLVector3 orient; - S32 out_volume; - F32 min_dist; - F32 max_dist; - - gAudiop->get3DParams(channel, &volume, &freq, &inside, &outside, &orient, &out_volume, &min_dist, &max_dist); - - if (mPage == 2) - { - sprintf(out_str,"%4.2f %4.2f %4.2f",orient.mV[VX],orient.mV[VY],orient.mV[VZ]); - LLFontGL::sMonospace->render(out_str, 103, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - - sprintf(out_str,"%4d %4d",inside, outside); - LLFontGL::sMonospace->render(out_str, 210, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - - sprintf(out_str,"%6d", out_volume); - LLFontGL::sMonospace->render(out_str, 280, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - } - else // mPage == 3 - { - F32 distance = 0.f; - if (gAudiop->isSourceAmbient(channel)) - { - distance = dist_vec(gAudiop->getSourcePos(channel),LLVector3::zero); - } - else - { - distance = dist_vec(gAudiop->getSourcePos(channel),gAudiop->getListenerPos()); - } - - sprintf(out_str,"%6.2f %6.2f %6.2f",distance, min_dist, max_dist); - LLFontGL::sMonospace->render(out_str, 103, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - - F32 gain = gAudiop->getSourceGain_dB(channel); - sprintf(out_str,"%7.2f",gain); - LLFontGL::sMonospace->render(out_str, 280, -channel*10, color, LLFontGL::LEFT, LLFontGL::TOP); - } - } - } - LLFontGL::sMonospace->render("Listener", 23, -(channel*10+5), color, LLFontGL::LEFT, LLFontGL::TOP); - - - if (mPage == 1) - { - LLVector3 lpos = gAudiop->getListenerPos(); - sprintf(out_str,"%6.2f %6.2f %6.2f",lpos.mV[VX],lpos.mV[VY],lpos.mV[VZ]); - LLFontGL::sMonospace->render(out_str, 103, -(channel*10+5), color, LLFontGL::LEFT, LLFontGL::TOP); - - F32 gain = gAudiop->getMasterGain_dB(); - sprintf(out_str,"%7.2f",gain); - LLFontGL::sMonospace->render(out_str, 280, -(channel*10+5), color, LLFontGL::LEFT, LLFontGL::TOP); - } - else if (mPage == 2) - { - sprintf(out_str,"cone orient inner outer gain"); - LLFontGL::sMonospace->render(out_str, 103, -(channel*10+5), color, LLFontGL::LEFT, LLFontGL::TOP); - } - else if (mPage == 3) - { - sprintf(out_str,"distance min max gain"); - LLFontGL::sMonospace->render(out_str, 103, -(channel*10+5), color, LLFontGL::LEFT, LLFontGL::TOP); - } - } - else - { - LLFontGL::sMonospace->render("No Audio Engine available", 50 , -175, - LLColor4(1.f,0.1f,0.1f,1.f), - LLFontGL::LEFT, LLFontGL::TOP); - } - - glPopMatrix(); - */ -} - - - - - - diff --git a/linden/indra/newview/llaudiostatus.h b/linden/indra/newview/llaudiostatus.h deleted file mode 100644 index fe7b67f..0000000 --- a/linden/indra/newview/llaudiostatus.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @file llaudiostatus.h - * @brief Audio channel allocation information - * - * Copyright (c) 2001-2007, 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 - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LL_LLAUDIOSTATUS_H -#define LL_LLAUDIOSTATUS_H - -#include "llmath.h" -#include "llview.h" - -//const char TAB = '\t'; -//const char DIVIDER[] = " / "; - -class LLAudiostatus : public LLView -{ - public: - S32 mPage; -protected: -public: - LLAudiostatus(const std::string& name, const LLRect& rect); - - virtual EWidgetType getWidgetType() const; - virtual LLString getWidgetTag() const; - - virtual void draw(); -}; - -#endif diff --git a/linden/indra/newview/llcallingcard.cpp b/linden/indra/newview/llcallingcard.cpp index 22a7f20..dfc99bf 100644 --- a/linden/indra/newview/llcallingcard.cpp +++ b/linden/indra/newview/llcallingcard.cpp @@ -294,6 +294,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) << "]" << llendl; } } + notifyObservers(); return new_buddy_count; } diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp index 66ffdc4..9798796 100644 --- a/linden/indra/newview/llchatbar.cpp +++ b/linden/indra/newview/llchatbar.cpp @@ -47,6 +47,7 @@ #include "llgesturemgr.h" #include "llkeyboard.h" #include "lllineeditor.h" +#include "llstatusbar.h" #include "lltextbox.h" #include "lluiconstants.h" #include "llviewergesture.h" // for triggering gestures @@ -70,15 +71,18 @@ const F32 AGENT_TYPING_TIMEOUT = 5.f; // seconds LLChatBar *gChatBar = NULL; -LLChatBarGestureObserver* LLChatBar::sObserver = NULL; +// legacy calllback glue +void toggleChatHistory(void* user_data); class LLChatBarGestureObserver : public LLGestureManagerObserver { public: - LLChatBarGestureObserver() {} + LLChatBarGestureObserver(LLChatBar* chat_barp) : mChatBar(chat_barp){} virtual ~LLChatBarGestureObserver() {} - virtual void changed() { gChatBar->refreshGestures(); } + virtual void changed() { mChatBar->refreshGestures(); } +private: + LLChatBar* mChatBar; }; @@ -86,12 +90,29 @@ public: // Functions // -LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) +//inline constructor +// for chat bars embedded in floaters, etc +LLChatBar::LLChatBar(const std::string& name) +: LLPanel(name, LLRect(), BORDER_NO), + mInputEditor(NULL), + mGestureLabelTimer(), + mLastSpecialChatChannel(0), + mIsBuilt(FALSE), + mDynamicLayout(FALSE), + mGestureCombo(NULL), + mObserver(NULL) +{ +} + +LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) : LLPanel(name, rect, BORDER_NO), mInputEditor(NULL), mGestureLabelTimer(), mLastSpecialChatChannel(0), - mIsBuilt(FALSE) + mIsBuilt(FALSE), + mDynamicLayout(TRUE), + mGestureCombo(NULL), + mObserver(NULL) { setIsChrome(TRUE); @@ -107,29 +128,6 @@ LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) // Start visible if we left the app while chatting. setVisible( gSavedSettings.getBOOL("ChatVisible") ); - mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "Chat Editor"); - if (mInputEditor) - { - mInputEditor->setCallbackUserData(this); - mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke); - mInputEditor->setFocusLostCallback(&onInputEditorFocusLost); - mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus ); - mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setRevertOnEsc( FALSE ); - mInputEditor->setIgnoreTab(TRUE); - mInputEditor->setPassDelete(TRUE); - mInputEditor->setMaxTextLength(1023); - mInputEditor->setEnableLineHistory(TRUE); - } - - // Build the list of gestures - refreshGestures(); - - sObserver = new LLChatBarGestureObserver; - gGestureManager.addObserver(sObserver); - - mIsBuilt = TRUE; - // Apply custom layout. layout(); @@ -142,23 +140,43 @@ LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) LLChatBar::~LLChatBar() { - delete sObserver; - sObserver = NULL; + delete mObserver; + mObserver = NULL; // LLView destructor cleans up children } BOOL LLChatBar::postBuild() { - childSetAction("History", LLFloaterChat::toggle, this); + childSetAction("History", toggleChatHistory, this); childSetAction("Say", onClickSay, this); childSetAction("Shout", onClickShout, this); - childSetCommitCallback("Gesture", onCommitGesture, this); - LLButton * sayp = static_cast(getChildByName("Say")); + + // attempt to bind to an existing combo box named gesture + setGestureCombo(LLUICtrlFactory::getComboBoxByName(this, "Gesture")); + + LLButton * sayp = static_cast(getChildByName("Say", TRUE)); if(sayp) { setDefaultBtn(sayp); } + mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "Chat Editor"); + if (mInputEditor) + { + mInputEditor->setCallbackUserData(this); + mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke); + mInputEditor->setFocusLostCallback(&onInputEditorFocusLost); + mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus ); + mInputEditor->setCommitOnFocusLost( FALSE ); + mInputEditor->setRevertOnEsc( FALSE ); + mInputEditor->setIgnoreTab(TRUE); + mInputEditor->setPassDelete(TRUE); + + mInputEditor->setMaxTextLength(1023); + } + + mIsBuilt = TRUE; + return TRUE; } @@ -206,7 +224,8 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) handled = TRUE; } } - else if ( KEY_ESCAPE == key ) + // only do this in main chatbar + else if ( KEY_ESCAPE == key && gChatBar == this) { stopChat(); @@ -219,6 +238,8 @@ BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) void LLChatBar::layout() { + if (!mDynamicLayout) return; + S32 rect_width = mRect.getWidth(); S32 count = 9; // number of elements in LLToolBar S32 pad = 4; @@ -281,13 +302,16 @@ void LLChatBar::refresh() // hide in mouselook, but keep previous visibility state //BOOL mouselook = gAgent.cameraMouselook(); // call superclass setVisible so that we don't overwrite the saved setting - LLPanel::setVisible(gSavedSettings.getBOOL("ChatVisible")); + if (mDynamicLayout) + { + LLPanel::setVisible(gSavedSettings.getBOOL("ChatVisible")); + } // HACK: Leave the name of the gesture in place for a few seconds. const F32 SHOW_GESTURE_NAME_TIME = 2.f; if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME) { - LLCtrlListInterface* gestures = childGetListInterface("Gesture"); + LLCtrlListInterface* gestures = mGestureCombo ? mGestureCombo->getListInterface() : NULL; if (gestures) gestures->selectFirstItem(); mGestureLabelTimer.stop(); } @@ -297,6 +321,8 @@ void LLChatBar::refresh() gAgent.stopTyping(); } + childSetValue("History", LLFloaterChat::instanceVisible(LLSD())); + childSetEnabled("Say", mInputEditor->getText().size() > 0); childSetEnabled("Shout", mInputEditor->getText().size() > 0); @@ -304,16 +330,18 @@ void LLChatBar::refresh() void LLChatBar::refreshGestures() { - LLCtrlListInterface* gestures = childGetListInterface("Gesture"); - if (gestures) + LLCtrlListInterface* gestures = mGestureCombo ? mGestureCombo->getListInterface() : NULL; + if (mGestureCombo && gestures) { //store current selection so we can maintain it - LLString cur_gesture = childGetValue("Gesture").asString(); + LLString cur_gesture = mGestureCombo->getValue().asString(); gestures->selectFirstItem(); - LLString label = childGetValue("Gesture").asString(); + LLString label = mGestureCombo->getValue().asString();; // clear gestures->clearRows(); - // add gestures + + // collect list of unique gestures + std::map unique; LLGestureManager::item_map_t::iterator it; for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it) { @@ -322,10 +350,18 @@ void LLChatBar::refreshGestures() { if (!gesture->mTrigger.empty()) { - gestures->addSimpleElement(gesture->mTrigger); + unique[gesture->mTrigger] = TRUE; } } } + + // ad unique gestures + std::map ::iterator it2; + for (it2 = unique.begin(); it2 != unique.end(); ++it2) + { + gestures->addSimpleElement((*it2).first); + } + gestures->sortByColumn(0, TRUE); // Insert label after sorting gestures->addSimpleElement(label, ADD_TOP); @@ -382,6 +418,23 @@ LLString LLChatBar::getCurrentChat() return mInputEditor ? mInputEditor->getText() : LLString::null; } +void LLChatBar::setGestureCombo(LLComboBox* combo) +{ + mGestureCombo = combo; + if (mGestureCombo) + { + mGestureCombo->setCommitCallback(onCommitGesture); + mGestureCombo->setCallbackUserData(this); + + // now register observer since we have a place to put the results + mObserver = new LLChatBarGestureObserver(this); + gGestureManager.addObserver(mObserver); + + // refresh list from current active gestures + refreshGestures(); + } +} + //----------------------------------------------------------------------- // Internal functions //----------------------------------------------------------------------- @@ -473,13 +526,13 @@ void LLChatBar::sendChat( EChatType type ) sendChatFromViewer(utf8_revised_text, type, TRUE); } } - childSetValue("Chat Editor", LLSD(LLString::null)); + childSetValue("Chat Editor", LLString::null); gAgent.stopTyping(); // If the user wants to stop chatting on hitting return, lose focus // and go out of chat mode. - if (gSavedSettings.getBOOL("CloseChatOnReturn")) + if (gChatBar == this && gSavedSettings.getBOOL("CloseChatOnReturn")) { stopChat(); } @@ -704,7 +757,7 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data) { LLChatBar* self = (LLChatBar*)data; - LLCtrlListInterface* gestures = self->childGetListInterface("Gesture"); + LLCtrlListInterface* gestures = self->mGestureCombo ? self->mGestureCombo->getListInterface() : NULL; if (gestures) { S32 index = gestures->getFirstSelectedIndex(); @@ -728,6 +781,14 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data) } } self->mGestureLabelTimer.start(); - // free focus back to chat bar - self->childSetFocus("Gesture", FALSE); + if (self->mGestureCombo != NULL) + { + // free focus back to chat bar + self->mGestureCombo->setFocus(FALSE); + } +} + +void toggleChatHistory(void* user_data) +{ + LLFloaterChat::toggleInstance(LLSD()); } diff --git a/linden/indra/newview/llchatbar.h b/linden/indra/newview/llchatbar.h index 32b0018..8a5acc6 100644 --- a/linden/indra/newview/llchatbar.h +++ b/linden/indra/newview/llchatbar.h @@ -33,23 +33,21 @@ #include "llframetimer.h" #include "llchat.h" -class LLButton; -class LLComboBox; class LLLineEditor; class LLMessageSystem; -class LLTextBox; -class LLTextEditor; class LLUICtrl; class LLUUID; class LLFrameTimer; -class LLStatGraph; class LLChatBarGestureObserver; +class LLComboBox; class LLChatBar : public LLPanel { public: - LLChatBar(const std::string& name, const LLRect& rect ); + // constructor for inline chat-bars (e.g. hosted in chat history window) + LLChatBar(const std::string& name); + LLChatBar(const std::string& name, const LLRect& rect); ~LLChatBar(); virtual BOOL postBuild(); @@ -71,6 +69,10 @@ public: BOOL inputEditorHasFocus(); LLString getCurrentChat(); + // since chat bar logic is reused for chat history + // gesture combo box might not be a direct child + void setGestureCombo(LLComboBox* combo); + // Send a chat (after stripping /20foo channel chats). // "Animate" means the nodding animation for regular text. void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); @@ -81,7 +83,6 @@ public: LLWString stripChannelNumber(const LLWString &mesg, S32* channel); // callbacks - static void onClickHistory( void* userdata ); static void onClickSay( void* userdata ); static void onClickShout( void* userdata ); @@ -109,8 +110,10 @@ protected: S32 mLastSpecialChatChannel; BOOL mIsBuilt; - - static LLChatBarGestureObserver* sObserver; + BOOL mDynamicLayout; + LLComboBox* mGestureCombo; + + LLChatBarGestureObserver* mObserver; }; extern LLChatBar *gChatBar; diff --git a/linden/indra/newview/llcolorswatch.cpp b/linden/indra/newview/llcolorswatch.cpp index 19490a2..2503649 100644 --- a/linden/indra/newview/llcolorswatch.cpp +++ b/linden/indra/newview/llcolorswatch.cpp @@ -260,21 +260,6 @@ void LLColorSwatchCtrl::setEnabled( BOOL enabled ) } -////////////////////////////////////////////////////////////////////////////// -// called when parent filters down a visibility changed message -void LLColorSwatchCtrl::onVisibilityChange ( BOOL curVisibilityIn ) -{ - // visibility changed - moved away to different tab for instance - cancel selection - //if ( ! curVisibilityIn) - //{ - // LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)LLFloater::getFloaterByHandle(mPickerHandle); - // if (pickerp) - // { - // pickerp->cancelSelection(); - // } - //} -} - void LLColorSwatchCtrl::setValue(const LLSD& value) { set(LLColor4(value), TRUE, TRUE); diff --git a/linden/indra/newview/llcolorswatch.h b/linden/indra/newview/llcolorswatch.h index b80a0e6..710d332 100644 --- a/linden/indra/newview/llcolorswatch.h +++ b/linden/indra/newview/llcolorswatch.h @@ -88,8 +88,6 @@ public: virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - virtual void onVisibilityChange ( BOOL curVisibilityIn ); - static void onColorChanged ( void* data, EColorPickOp pick_op = COLOR_CHANGE ); protected: diff --git a/linden/indra/newview/llcontroldef.cpp b/linden/indra/newview/llcontroldef.cpp index 7481d99..dffaa36 100644 --- a/linden/indra/newview/llcontroldef.cpp +++ b/linden/indra/newview/llcontroldef.cpp @@ -43,6 +43,33 @@ #include "v3color.h" #include "llfirstuse.h" +// For Listeners +#include "audioengine.h" +#include "llagent.h" +#include "llconsole.h" +#include "lldrawpoolterrain.h" +#include "llflexibleobject.h" +#include "llglslshader.h" +#include "llmediaengine.h" +#include "llpanelgeneral.h" +#include "llpanelinput.h" +#include "llsky.h" +#include "llviewerimagelist.h" +#include "llviewerthrottle.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llvosky.h" +#include "llvotree.h" +#include "llvovolume.h" +#include "llworld.h" +#include "pipeline.h" +#include "viewer.h" +#include "llviewerjoystick.h" +#include "llviewerparcelmgr.h" +#include "llparcel.h" +#include "llnotify.h" +#include "llkeyboard.h" + void declare_settings() { // Somewhat under 1024 by 768 @@ -61,7 +88,7 @@ void declare_settings() gSavedSettings.declareColor4("SystemChatColor", LLColor4(0.8f, 1.f, 1.f, 1.f), "Color of chat messages from SL System"); gSavedSettings.declareColor4("AgentChatColor", LLColor4(1.0f, 1.0f, 1.0f, 1.0f), "Color of chat messages from other residents"); gSavedSettings.declareColor4("ObjectChatColor", LLColor4(0.7f, 0.9f, 0.7f, 1.0f), "Color of chat messages from objects"); - gSavedSettings.declareColor4("llOwnerSayChatColor", LLColor4(0.7f, 0.0f, 0.7f, 1.0f), "Color of chat messages from objects only visible to the owner"); + gSavedSettings.declareColor4("llOwnerSayChatColor", LLColor4(0.99f, 0.99f, 0.69f, 1.0f), "Color of chat messages from objects only visible to the owner"); gSavedSettings.declareColor4("BackgroundChatColor", LLColor4(0.f, 0.f, 0.f, 1.0f), "Color of chat bubble background"); gSavedSettings.declareColor4("ScriptErrorColor", LLColor4(0.82f, 0.82f, 0.99f, 1.0f), "Color of script error messages"); gSavedSettings.declareColor4("HTMLLinkColor", LLColor4(0.6f, 0.6f, 1.0f, 1.0f), "Color of hyperlinks"); @@ -237,6 +264,75 @@ void declare_settings() gSavedSettings.declareBOOL("ChatShowTimestamps", TRUE, "Show timestamps in chat"); + gSavedSettings.declareBOOL("EnableVoiceChat", FALSE, "Enable talking to other residents with a microphone"); + gSavedSettings.declareBOOL("VoiceCallsFriendsOnly", FALSE, "Only accept voice calls from residents on your friends list"); + gSavedSettings.declareBOOL("PTTCurrentlyEnabled", TRUE, "", NO_PERSIST); + gSavedSettings.declareBOOL("EnablePushToTalk", TRUE, "Must hold down a key or moouse button when talking into your microphone"); + gSavedSettings.declareString("PushToTalkButton", "MiddleMouse", "Which button or keyboard key is used for push-to-talk"); + gSavedSettings.declareBOOL("PushToTalkToggle", FALSE, "Should the push-to-talk button behave as a toggle"); + gSavedSettings.declareS32("VoiceEarLocation", 0, "Location of the virtual ear for voice"); + gSavedSettings.declareString("VivoxDebugServerName", "bhd.vivox.com", "Hostname of the vivox account server to use for voice when not connected to Agni."); + gSavedSettings.declareColor4("SpeakingColor", LLColor4(0.f, 1.f, 0.f, 1.f), "Color of various indicators when resident is speaking on a voice channel."); + gSavedSettings.declareColor4("OverdrivenColor", LLColor4(1.f, 0.f, 0.f, 1.f), "Color of various indicators when resident is speaking too loud."); + gSavedSettings.declareString("VoiceInputAudioDevice", "Default", "Audio input device to use for voice"); + gSavedSettings.declareString("VoiceOutputAudioDevice", "Default", "Audio output device to use for voice"); + gSavedSettings.declareString("VivoxDebugLevel", "-1", "Logging level to use when launching the vivox daemon"); + + //voice amplitude images; + + /* + gSavedSettings.declareString("VoiceImageLevel0", "5b41b4c3-eb70-0f0f-17d9-1765cbd07d39", "Texture UUID for voice image level 0"); + gSavedSettings.declareString("VoiceImageLevel1", "b06ffd0a-7bfe-0449-0bbc-df291f1857c4", "Texture UUID for voice image level 1"); + gSavedSettings.declareString("VoiceImageLevel2", "bfa16494-b731-5b59-3260-9e4fd29d63f7", "Texture UUID for voice image level 2"); + gSavedSettings.declareString("VoiceImageLevel3", "6951074f-de1d-3c55-cb2f-e972877f7f81", "Texture UUID for voice image level 3"); + gSavedSettings.declareString("VoiceImageLevel4", "ce3df80a-f0c5-a7cb-f5bc-d3bb38949d0d", "Texture UUID for voice image level 4"); + gSavedSettings.declareString("VoiceImageLevel5", "8d0e359c-5cea-bdf5-b6b0-32d2fea6355c", "Texture UUID for voice image level 5"); + gSavedSettings.declareString("VoiceImageLevel6", "ad9e64e0-a763-5d8c-f2e8-7b5dfdb7f20f", "Texture UUID for voice image level 6"); + */ + + /* + // Jeffrey's first version + gSavedSettings.declareString("VoiceImageLevel0", "5b41b4c3-eb70-0f0f-17d9-1765cbd07d39", "Texture UUID for voice image level 0"); + gSavedSettings.declareString("VoiceImageLevel1", "cde76ae8-0044-d575-8e2c-65fb0a14cbde", "Texture UUID for voice image level 1"); + gSavedSettings.declareString("VoiceImageLevel2", "cde76ae8-0044-d575-8e2c-65fb0a14cbde", "Texture UUID for voice image level 2"); + gSavedSettings.declareString("VoiceImageLevel3", "cde76ae8-0044-d575-8e2c-65fb0a14cbde", "Texture UUID for voice image level 3"); + gSavedSettings.declareString("VoiceImageLevel4", "cde76ae8-0044-d575-8e2c-65fb0a14cbde", "Texture UUID for voice image level 4"); + gSavedSettings.declareString("VoiceImageLevel5", "cde76ae8-0044-d575-8e2c-65fb0a14cbde", "Texture UUID for voice image level 5"); + gSavedSettings.declareString("VoiceImageLevel6", "cde76ae8-0044-d575-8e2c-65fb0a14cbde", "Texture UUID for voice image level 6"); + */ + + // Brent's first version + /* + gSavedSettings.declareString("VoiceImageLevel0", "5b41b4c3-eb70-0f0f-17d9-1765cbd07d39", "Texture UUID for voice image level 0"); + gSavedSettings.declareString("VoiceImageLevel1", "72365124-c7a7-a1f9-3d7a-d8e521eb5011", "Texture UUID for voice image level 1"); + gSavedSettings.declareString("VoiceImageLevel2", "72365124-c7a7-a1f9-3d7a-d8e521eb5011", "Texture UUID for voice image level 2"); + gSavedSettings.declareString("VoiceImageLevel3", "72365124-c7a7-a1f9-3d7a-d8e521eb5011", "Texture UUID for voice image level 3"); + gSavedSettings.declareString("VoiceImageLevel4", "72365124-c7a7-a1f9-3d7a-d8e521eb5011", "Texture UUID for voice image level 4"); + gSavedSettings.declareString("VoiceImageLevel5", "72365124-c7a7-a1f9-3d7a-d8e521eb5011", "Texture UUID for voice image level 5"); + gSavedSettings.declareString("VoiceImageLevel6", "72365124-c7a7-a1f9-3d7a-d8e521eb5011", "Texture UUID for voice image level 6"); + */ + + /* + // Brent's second version + gSavedSettings.declareString("VoiceImageLevel0", "5b41b4c3-eb70-0f0f-17d9-1765cbd07d39", "Texture UUID for voice image level 0"); + gSavedSettings.declareString("VoiceImageLevel1", "4ee6a7ac-472e-b5ff-7125-f6213798cbee", "Texture UUID for voice image level 1"); + gSavedSettings.declareString("VoiceImageLevel2", "4ee6a7ac-472e-b5ff-7125-f6213798cbee", "Texture UUID for voice image level 2"); + gSavedSettings.declareString("VoiceImageLevel3", "4ee6a7ac-472e-b5ff-7125-f6213798cbee", "Texture UUID for voice image level 3"); + gSavedSettings.declareString("VoiceImageLevel4", "4ee6a7ac-472e-b5ff-7125-f6213798cbee", "Texture UUID for voice image level 4"); + gSavedSettings.declareString("VoiceImageLevel5", "4ee6a7ac-472e-b5ff-7125-f6213798cbee", "Texture UUID for voice image level 5"); + gSavedSettings.declareString("VoiceImageLevel6", "4ee6a7ac-472e-b5ff-7125-f6213798cbee", "Texture UUID for voice image level 6"); + */ + + // Jeffrey's tweak on 4/9/07 + gSavedSettings.declareString("VoiceImageLevel0", "041ee5a0-cb6a-9ac5-6e49-41e9320507d5", "Texture UUID for voice image level 0"); + gSavedSettings.declareString("VoiceImageLevel1", "29de489d-0491-fb00-7dab-f9e686d31e83", "Texture UUID for voice image level 1"); + gSavedSettings.declareString("VoiceImageLevel2", "29de489d-0491-fb00-7dab-f9e686d31e83", "Texture UUID for voice image level 2"); + gSavedSettings.declareString("VoiceImageLevel3", "29de489d-0491-fb00-7dab-f9e686d31e83", "Texture UUID for voice image level 3"); + gSavedSettings.declareString("VoiceImageLevel4", "29de489d-0491-fb00-7dab-f9e686d31e83", "Texture UUID for voice image level 4"); + gSavedSettings.declareString("VoiceImageLevel5", "29de489d-0491-fb00-7dab-f9e686d31e83", "Texture UUID for voice image level 5"); + gSavedSettings.declareString("VoiceImageLevel6", "29de489d-0491-fb00-7dab-f9e686d31e83", "Texture UUID for voice image level 6"); + + //------------------------------------------------------------------------ // Caution Script Permission Prompts //------------------------------------------------------------------------ @@ -419,6 +515,7 @@ void declare_settings() gSavedSettings.declareBOOL("CloseChatOnReturn", FALSE, "Close chat after hitting return"); // Copy IM messages into chat history + gSavedSettings.declareBOOL("ChatHistoryTornOff", FALSE, "Show chat history window separately from Communicate window."); gSavedSettings.declareBOOL("IMInChatHistory", FALSE, "Copy IM into chat history"); gSavedSettings.declareBOOL("IMShowTimestamps", TRUE, "Show timestamps in IM"); @@ -591,11 +688,10 @@ void declare_settings() gSavedSettings.declareBOOL("ShowLeaders", FALSE, "", NO_PERSIST); gSavedSettings.declareBOOL("ShowDirectory", FALSE, "", NO_PERSIST); - gSavedSettings.declareBOOL("ShowFriends", FALSE, "", NO_PERSIST); gSavedSettings.declareBOOL("AutoLoadWebProfiles", FALSE, "Automatically load ALL profile webpages without asking first."); - gSavedSettings.declareBOOL("ShowIM", FALSE, "", NO_PERSIST); + gSavedSettings.declareBOOL("ShowCommunicate", FALSE, "", NO_PERSIST); gSavedSettings.declareBOOL("ShowChatHistory", FALSE, "", NO_PERSIST); #ifdef LL_RELEASE_FOR_DOWNLOAD @@ -636,6 +732,7 @@ void declare_settings() LLFirstUse::addConfigVariable("FirstStreamingMusic"); LLFirstUse::addConfigVariable("FirstStreamingVideo"); LLFirstUse::addConfigVariable("FirstSculptedPrim"); + LLFirstUse::addConfigVariable("FirstVoice"); gSavedSettings.declareBOOL("ShowDebugConsole", FALSE, "Show log in SL window"); gSavedSettings.declareBOOL("ShowDebugStats", FALSE, "Show performance stats display"); @@ -797,6 +894,9 @@ void declare_settings() //gSavedSettings.declareS32("BWRadio", 0, "[NOT USED]"); + gSavedSettings.declareRect("ChatterboxRect", LLRect(0, 400, 350, 0), "Rectangle for chatterbox window"); + gSavedSettings.declareRect("FloaterActiveSpeakersRect", LLRect(0, 300, 250, 0), "Rectangle for active speakers window"); + // Avatar customizing floaters gSavedSettings.declareRect("FloaterCustomizeAppearanceRect", LLRect(0, 540, 494, 0), "Rectangle for avatar customization window"); @@ -923,6 +1023,9 @@ void declare_settings() // Script Panel //gSavedSettings.declareRect("ScriptPanelRect", LLRect(250, 175 + 400, 250 + 400, 175), "[NOT USED]"); + // volume floater + gSavedSettings.declareRect("FloaterAudioVolumeRect", LLRect(0, 440, 470, 0), "Rectangle for Audio Volume window"); + // Radio button sets gSavedSettings.declareU32("AvatarSex", 0, "", NO_PERSIST); @@ -1012,16 +1115,20 @@ void declare_settings() gSavedSettings.declareRect("HtmlFindRect", LLRect(16,650,600,128), "Rectangle for HTML find window"); // Audio - gSavedSettings.declareF32("AudioLevelDistance", 1.0f, "Scale factor for audio engine (multiple of world scale, 2.0 = audio falls off twice as fast)"); - gSavedSettings.declareF32("AudioLevelDoppler", 1.0f, "Scale of doppler effect on moving audio sources (1.0 = normal, <1.0 = diminished doppler effect, >1.0 = enhanced doppler effect)"); - gSavedSettings.declareF32("AudioLevelFootsteps", 0.15f, "Relative audio level of footstep sound effects"); gSavedSettings.declareF32("AudioLevelMaster", 1.0f, "Master audio level, or overall volume"); + gSavedSettings.declareF32("AudioLevelSFX", 1.0f, "Audio level of in-world sound effects"); + gSavedSettings.declareF32("AudioLevelAmbient",0.5f, "Audio level of environment sounds"); + gSavedSettings.declareF32("AudioLevelUI", 0.5f, "Audio level of UI sound effects"); gSavedSettings.declareF32("AudioLevelMusic", 1.0f, "Audio level of streaming music"); - gSavedSettings.declareF32("MediaAudioVolume", 1.0f, "Audio level of Quicktime movies"); + gSavedSettings.declareF32("AudioLevelVoice", 1.0f, "Audio level of voice chat"); + gSavedSettings.declareF32("AudioLevelMedia", 1.0f, "Audio level of Quicktime movies"); + gSavedSettings.declareF32("AudioLevelMic", 1.0f, "Audio level of microphone input"); + +// gSavedSettings.declareF32("MediaAudioVolume", 1.0f, "Audio level of Quicktime movies"); // removed + + gSavedSettings.declareF32("AudioLevelDistance", 1.0f, "Scale factor for audio engine (multiple of world scale, 2.0 = audio falls off twice as fast)"); + gSavedSettings.declareF32("AudioLevelDoppler", 1.0f, "Scale of doppler effect on moving audio sources (1.0 = normal, <1.0 = diminished doppler effect, >1.0 = enhanced doppler effect)"); gSavedSettings.declareF32("AudioLevelRolloff", 1.0f, "Controls the distance-based dropoff of audio volume (fraction or multiple of default audio rolloff)"); - gSavedSettings.declareF32("AudioLevelUI", 0.5f, "Audio level of UI sound effects"); - //gSavedSettings.declareF32("AudioLevelWater", 0.0f, "[NOT USED]"); - gSavedSettings.declareF32("AudioLevelWind", 0.5f, "Audio level of wind sound effect"); gSavedSettings.declareS32("AudioDefaultBitrate", 64, "Data streaming rate of uploaded audio samples (thousands of bits per second)"); gSavedSettings.declareBOOL("AudioStreamingMusic", FALSE, "Enable streaming audio"); @@ -1107,11 +1214,7 @@ void declare_settings() gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "Turns on \"Debug\" menu"); gSavedSettings.declareS32("ServerChoice", 0, "[DO NOT MODIFY] Controls which grid you connect to"); gSavedSettings.declareString("CustomServer", "", "Specifies IP address or hostname of userserver to which you connect"); -#ifdef LL_RELEASE_FOR_DOWNLOAD gSavedSettings.declareBOOL("UseDebugLogin", FALSE, "Provides extra control over which grid to connect to"); -#else - gSavedSettings.declareBOOL("UseDebugLogin", TRUE, "Provides extra control over which grid to connect to" ); -#endif // First run is true on the first startup of a given installation. // It is not related to whether your ACCOUNT has been logged in before. @@ -1146,7 +1249,15 @@ void declare_settings() gSavedSettings.declareBOOL("EditCameraMovement", FALSE, "When entering build mode, camera moves up above avatar"); gSavedSettings.declareBOOL("AppearanceCameraMovement", TRUE, "When entering appearance editing mode, camera zooms in on currently selected portion of avatar"); - gSavedSettings.declareBOOL("AltShowsPhysical", FALSE, "When ALT key is held down, physical objects are rendered in red."); + //gSavedSettings.declareBOOL("AltShowsPhysical", FALSE, "When ALT key is held down, physical objects are rendered in red."); + gSavedSettings.declareBOOL("BeaconAlwaysOn", FALSE, "Beacons / highlighting always on"); + gSavedSettings.declareBOOL("scriptsbeacon", FALSE, "Beacon / Highlight scripted objects"); + gSavedSettings.declareBOOL("physicalbeacon", TRUE, "Beacon / Highlight physical objects"); + gSavedSettings.declareBOOL("soundsbeacon", FALSE, "Beacon / Highlight sound generators"); + gSavedSettings.declareBOOL("particlesbeacon", FALSE, "Beacon / Highlight particle generators"); + gSavedSettings.declareBOOL("scripttouchbeacon", TRUE, "Beacon / Highlight scripted objects with touch function"); + gSavedSettings.declareBOOL("renderbeacons", FALSE, "Beacon / Highlight particle generators"); + gSavedSettings.declareBOOL("renderhighlights", TRUE, "Beacon / Highlight scripted objects with touch function"); gSavedSettings.declareBOOL("MuteAudio", FALSE, "All audio plays at 0 volume (streaming audio still takes up bandwidth, for example)"); gSavedSettings.declareBOOL("MuteWhenMinimized", TRUE, "Mute audio when SL window is minimized"); @@ -1317,6 +1428,12 @@ void declare_settings() gSavedSettings.declareBOOL("FlycamAbsolute", FALSE, "Treat Flycam values as absolute positions (not deltas)."); gSavedSettings.declareBOOL("FlycamZoomDirect", FALSE, "Map flycam zoom axis directly to camera zoom."); + // Vector Processor & Math + gSavedSettings.declareBOOL("VectorizePerfTest", TRUE, "Test SSE/vectorization performance and choose fastest version."); + gSavedSettings.declareBOOL("VectorizeEnable", FALSE, "Enable general vector operations and data alignment."); + gSavedSettings.declareBOOL("VectorizeSkin", TRUE, "Enable vector operations for avatar skinning."); + gSavedSettings.declareU32( "VectorizeProcessor", 0, "0=Compiler Default, 1=SSE, 2=SSE2, autodetected", NO_PERSIST); + // // crash_settings.xml // @@ -1333,3 +1450,460 @@ void fixup_settings() gSavedSettings.setBOOL("AnimateTextures", TRUE); // Force AnimateTextures to always be on #endif } + +//////////////////////////////////////////////////////////////////////////// +// Listeners + +class LLAFKTimeoutListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gAFKTimeout = (F32) event->getValue().asReal(); + return true; + } +}; +static LLAFKTimeoutListener afk_timeout_listener; + +class LLMouseSensitivityListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gMouseSensitivity = (F32) event->getValue().asReal(); + return true; + } +}; +static LLMouseSensitivityListener mouse_sensitivity_listener; + + +class LLInvertMouseListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gInvertMouse = event->getValue().asBoolean(); + return true; + } +}; +static LLInvertMouseListener invert_mouse_listener; + +class LLRenderAvatarMouselookListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOAvatar::sVisibleInFirstPerson = event->getValue().asBoolean(); + return true; + } +}; +static LLRenderAvatarMouselookListener render_avatar_mouselook_listener; + +class LLRenderFarClipListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + F32 draw_distance = (F32) event->getValue().asReal(); + gAgent.mDrawDistance = draw_distance; + if (gWorldPointer) + { + gWorldPointer->setLandFarClip(draw_distance); + } + return true; + } +}; +static LLRenderFarClipListener render_far_clip_listener; + +class LLTerrainDetailListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLDrawPoolTerrain::sDetailMode = event->getValue().asInteger(); + return true; + } +}; +static LLTerrainDetailListener terrain_detail_listener; + + +class LLSetShaderListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLShaderMgr::setShaders(); + return true; + } +}; +static LLSetShaderListener set_shader_listener; + +class LLReleaseGLBufferListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gPipeline.releaseGLBuffers(); + LLShaderMgr::setShaders(); + return true; + } +}; +static LLReleaseGLBufferListener release_gl_buffer_listener; + +class LLVolumeLODListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOVolume::sLODFactor = (F32) event->getValue().asReal(); + LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; + return true; + } +}; +static LLVolumeLODListener volume_lod_listener; + +class LLAvatarLODListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOAvatar::sLODFactor = (F32) event->getValue().asReal(); + return true; + } +}; +static LLAvatarLODListener avatar_lod_listener; + +class LLTreeLODListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOTree::sTreeFactor = (F32) event->getValue().asReal(); + return true; + } +}; +static LLTreeLODListener tree_lod_listener; + +class LLFlexLODListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVolumeImplFlexible::sUpdateFactor = (F32) event->getValue().asReal(); + return true; + } +}; +static LLFlexLODListener flex_lod_listener; + +class LLGammaListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + F32 gamma = (F32) event->getValue().asReal(); + if (gamma == 0.0f) + { + gamma = 1.0f; // restore normal gamma + } + if (gamma != gViewerWindow->getWindow()->getGamma()) + { + // Only save it if it's changed + if (!gViewerWindow->getWindow()->setGamma(gamma)) + { + llwarns << "setGamma failed!" << llendl; + } + } + + return true; + } +}; +static LLGammaListener gamma_listener; + +class LLNightBrightnessListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOSky::sNighttimeBrightness = (F32) event->getValue().asReal(); + return true; + } +}; +static LLNightBrightnessListener night_brightness_listener; + +const F32 MAX_USER_FOG_RATIO = 4.f; +const F32 MIN_USER_FOG_RATIO = 0.5f; + +class LLFogRatioListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + F32 fog_ratio = llmax(MIN_USER_FOG_RATIO, + llmin((F32) event->getValue().asReal(), + MAX_USER_FOG_RATIO)); + gSky.setFogRatio(fog_ratio); + return true; + } +}; +static LLFogRatioListener fog_ratio_listener; + +class LLMaxPartCountListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerPartSim::setMaxPartCount(event->getValue().asInteger()); + return true; + } +}; +static LLMaxPartCountListener max_partCount_listener; + +const S32 MAX_USER_COMPOSITE_LIMIT = 100; +const S32 MIN_USER_COMPOSITE_LIMIT = 0; + +class LLCompositeLimitListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + S32 composite_limit = llmax(MIN_USER_COMPOSITE_LIMIT, + llmin((S32)event->getValue().asInteger(), + MAX_USER_COMPOSITE_LIMIT)); + LLVOAvatar::sMaxOtherAvatarsToComposite = composite_limit; + return true; + } +}; +static LLCompositeLimitListener composite_limit_listener; + +class LLVideoMemoryListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gImageList.updateMaxResidentTexMem(event->getValue().asInteger()); + return true; + } +}; +static LLVideoMemoryListener video_memory_listener; + +class LLBandwidthListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gViewerThrottle.setMaxBandwidth((F32) event->getValue().asReal()); + return true; + } +}; +static LLBandwidthListener bandwidth_listener; + +class LLChatFontSizeListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gConsole->setFontSize(event->getValue().asInteger()); + return true; + } +}; +static LLChatFontSizeListener chat_font_size_listener; + +class LLChatPersistTimeListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gConsole->setLinePersistTime((F32) event->getValue().asReal()); + return true; + } +}; +static LLChatPersistTimeListener chat_persist_time_listener; + +class LLConsoleMaxLinesListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gConsole->setMaxLines(event->getValue().asInteger()); + return true; + } +}; +static LLConsoleMaxLinesListener console_max_lines_listener; + +// Listener for all volume settings +class LLAudioListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + audio_update_volume(true); + return true; + } +}; +static LLAudioListener audio_listener; + +class LLJoystickListener : public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerJoystick::updateCamera(TRUE); + return true; + } +}; +static LLJoystickListener joystick_listener; + +void stop_video(); +void prepare_video(const LLParcel *parcel); + +class LLAudioStreamMusicListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + if (gAudiop) + { + if ( event->getValue().asBoolean() ) + { + if (gParcelMgr + && gParcelMgr->getAgentParcel() + && gParcelMgr->getAgentParcel()->getMusicURL()) + { + // if stream is already playing, don't call this + // otherwise music will briefly stop + if ( ! gAudiop->isInternetStreamPlaying() ) + { + gAudiop->startInternetStream(gParcelMgr->getAgentParcel()->getMusicURL()); + } + } + } + else + { + gAudiop->stopInternetStream(); + } + } + return true; + } +}; + +static LLAudioStreamMusicListener audio_stream_music_listener; + + + +class LLAudioStreamMediaListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + if (LLMediaEngine::getInstance() && LLMediaEngine::getInstance()->isAvailable()) + { + if (event->getValue().asBoolean()) + { + gMessageSystem->setHandlerFunc ( "ParcelMediaCommandMessage", LLMediaEngine::process_parcel_media ); + gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", LLMediaEngine::process_parcel_media_update ); + if ( ( gParcelMgr ) && + ( gParcelMgr->getAgentParcel () ) && + ( gParcelMgr->getAgentParcel()->getMediaURL () ) ) + { + prepare_video ( gParcelMgr->getAgentParcel () ); + } + } + else + { + gMessageSystem->setHandlerFunc("ParcelMediaCommandMessage", null_message_callback); + gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", null_message_callback ); + stop_video(); + } + } + else + { + if (gSavedSettings.getWarning("QuickTimeInstalled")) + { + gSavedSettings.setWarning("QuickTimeInstalled", FALSE); + + LLNotifyBox::showXml("NoQuickTime" ); + } + } + + return true; + } +}; + +static LLAudioStreamMediaListener audio_stream_media_listener; + + +class LLUseOcclusionListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLPipeline::sUseOcclusion = (event->getValue().asBoolean() && gGLManager.mHasOcclusionQuery && + !gUseWireframe); + return true; + } +}; +static LLUseOcclusionListener use_occlusion_listener; + +class LLNumpadControlListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + if (gKeyboard) + { + gKeyboard->setNumpadDistinct(static_cast(event->getValue().asInteger())); + } + return true; + } +}; + +static LLNumpadControlListener numpad_control_listener; + +class LLRenderUseVBOListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gPipeline.setUseVBO(event->getValue().asBoolean()); + return true; + } +}; +static LLRenderUseVBOListener render_use_vbo_listener; + +class LLRenderLightingDetailListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gPipeline.setLightingDetail(event->getValue().asInteger()); + return true; + } +}; +static LLRenderLightingDetailListener render_lighting_detail_listener; + +//////////////////////////////////////////////////////////////////////////// + +void settings_setup_listeners() +{ + gSavedSettings.getControl("FirstPersonAvatarVisible")->addListener(&render_avatar_mouselook_listener); + gSavedSettings.getControl("MouseSensitivity")->addListener(&mouse_sensitivity_listener); + gSavedSettings.getControl("InvertMouse")->addListener(&invert_mouse_listener); + gSavedSettings.getControl("AFKTimeout")->addListener(&afk_timeout_listener); + gSavedSettings.getControl("RenderFarClip")->addListener(&render_far_clip_listener); + gSavedSettings.getControl("RenderTerrainDetail")->addListener(&terrain_detail_listener); + gSavedSettings.getControl("RenderRippleWater")->addListener(&set_shader_listener); + gSavedSettings.getControl("RenderAvatarVP")->addListener(&set_shader_listener); + gSavedSettings.getControl("VertexShaderEnable")->addListener(&set_shader_listener); + gSavedSettings.getControl("RenderDynamicReflections")->addListener(&set_shader_listener); + gSavedSettings.getControl("RenderGlow")->addListener(&release_gl_buffer_listener); + gSavedSettings.getControl("RenderGlowResolution")->addListener(&release_gl_buffer_listener); + gSavedSettings.getControl("RenderAvatarMode")->addListener(&set_shader_listener); + gSavedSettings.getControl("RenderVolumeLODFactor")->addListener(&volume_lod_listener); + gSavedSettings.getControl("RenderAvatarLODFactor")->addListener(&avatar_lod_listener); + gSavedSettings.getControl("RenderTreeLODFactor")->addListener(&tree_lod_listener); + gSavedSettings.getControl("RenderFlexTimeFactor")->addListener(&flex_lod_listener); + gSavedSettings.getControl("ThrottleBandwidthKBPS")->addListener(&bandwidth_listener); + gSavedSettings.getControl("RenderGamma")->addListener(&gamma_listener); + gSavedSettings.getControl("RenderNightBrightness")->addListener(&night_brightness_listener); + gSavedSettings.getControl("RenderFogRatio")->addListener(&fog_ratio_listener); + gSavedSettings.getControl("RenderMaxPartCount")->addListener(&max_partCount_listener); + gSavedSettings.getControl("AvatarCompositeLimit")->addListener(&composite_limit_listener); + gSavedSettings.getControl("GraphicsCardMemorySetting")->addListener(&video_memory_listener); + gSavedSettings.getControl("ChatFontSize")->addListener(&chat_font_size_listener); + gSavedSettings.getControl("ChatPersistTime")->addListener(&chat_persist_time_listener); + gSavedSettings.getControl("ConsoleMaxLines")->addListener(&console_max_lines_listener); + gSavedSettings.getControl("UseOcclusion")->addListener(&use_occlusion_listener); + gSavedSettings.getControl("AudioLevelMaster")->addListener(&audio_listener); +// gSavedSettings.getControl("AudioLevelSFX")->addListener(&audio_volume_listener); // no need for listener +// gSavedSettings.getControl("AudioLevelUI")->addListener(&audio_volume_listener); // no need for listener + gSavedSettings.getControl("AudioLevelAmbient")->addListener(&audio_listener); + gSavedSettings.getControl("AudioLevelMusic")->addListener(&audio_listener); + gSavedSettings.getControl("AudioLevelMedia")->addListener(&audio_listener); + gSavedSettings.getControl("AudioLevelVoice")->addListener(&audio_listener); + gSavedSettings.getControl("AudioLevelDistance")->addListener(&audio_listener); + gSavedSettings.getControl("AudioLevelDoppler")->addListener(&audio_listener); + gSavedSettings.getControl("AudioLevelRolloff")->addListener(&audio_listener); + gSavedSettings.getControl("AudioStreamingMusic")->addListener(&audio_stream_music_listener); + gSavedSettings.getControl("AudioStreamingVideo")->addListener(&audio_stream_media_listener); + gSavedSettings.getControl("MuteAudio")->addListener(&audio_listener); + gSavedSettings.getControl("RenderVBOEnable")->addListener(&render_use_vbo_listener); + gSavedSettings.getControl("RenderLightingDetail")->addListener(&render_lighting_detail_listener); + gSavedSettings.getControl("NumpadControl")->addListener(&numpad_control_listener); + gSavedSettings.getControl("FlycamAxis0")->addListener(&joystick_listener); + gSavedSettings.getControl("FlycamAxis1")->addListener(&joystick_listener); + gSavedSettings.getControl("FlycamAxis2")->addListener(&joystick_listener); + gSavedSettings.getControl("FlycamAxis3")->addListener(&joystick_listener); + gSavedSettings.getControl("FlycamAxis4")->addListener(&joystick_listener); + gSavedSettings.getControl("FlycamAxis5")->addListener(&joystick_listener); + gSavedSettings.getControl("FlycamAxis6")->addListener(&joystick_listener); +} diff --git a/linden/indra/newview/lldebugmessagebox.cpp b/linden/indra/newview/lldebugmessagebox.cpp index 948b96a..b1f44e9 100644 --- a/linden/indra/newview/lldebugmessagebox.cpp +++ b/linden/indra/newview/lldebugmessagebox.cpp @@ -53,25 +53,25 @@ LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarTy switch(var_type) { case VAR_TYPE_F32: - mSlider1 = new LLSliderCtrl("slider 1", LLRect(20,130,190,110), title, NULL, 70, 130, TRUE, TRUE, NULL, NULL, *((F32*)var), -100.f, 100.f, 0.1f, NULL); + mSlider1 = new LLSliderCtrl("slider 1", LLRect(20,130,190,110), title, NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, *((F32*)var), -100.f, 100.f, 0.1f, NULL); mSlider1->setPrecision(3); addChild(mSlider1); mSlider2 = NULL; mSlider3 = NULL; break; case VAR_TYPE_S32: - mSlider1 = new LLSliderCtrl("slider 1", LLRect(20,100,190,80), title, NULL, 70, 130, TRUE, TRUE, NULL, NULL, (F32)*((S32*)var), -255.f, 255.f, 1.f, NULL); + mSlider1 = new LLSliderCtrl("slider 1", LLRect(20,100,190,80), title, NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, (F32)*((S32*)var), -255.f, 255.f, 1.f, NULL); mSlider1->setPrecision(0); addChild(mSlider1); mSlider2 = NULL; mSlider3 = NULL; break; case VAR_TYPE_VEC3: - mSlider1 = new LLSliderCtrl("slider 1", LLRect(20,130,190,110), "x: ", NULL, 70, 130, TRUE, TRUE, NULL, NULL, ((LLVector3*)var)->mV[VX], -100.f, 100.f, 0.1f, NULL); + mSlider1 = new LLSliderCtrl("slider 1", LLRect(20,130,190,110), "x: ", NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, ((LLVector3*)var)->mV[VX], -100.f, 100.f, 0.1f, NULL); mSlider1->setPrecision(3); - mSlider2 = new LLSliderCtrl("slider 2", LLRect(20,100,190,80), "y: ", NULL, 70, 130, TRUE, TRUE, NULL, NULL, ((LLVector3*)var)->mV[VY], -100.f, 100.f, 0.1f, NULL); + mSlider2 = new LLSliderCtrl("slider 2", LLRect(20,100,190,80), "y: ", NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, ((LLVector3*)var)->mV[VY], -100.f, 100.f, 0.1f, NULL); mSlider2->setPrecision(3); - mSlider3 = new LLSliderCtrl("slider 3", LLRect(20,70,190,50), "z: ", NULL, 70, 130, TRUE, TRUE, NULL, NULL, ((LLVector3*)var)->mV[VZ], -100.f, 100.f, 0.1f, NULL); + mSlider3 = new LLSliderCtrl("slider 3", LLRect(20,70,190,50), "z: ", NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, ((LLVector3*)var)->mV[VZ], -100.f, 100.f, 0.1f, NULL); mSlider3->setPrecision(3); addChild(mSlider1); addChild(mSlider2); diff --git a/linden/indra/newview/lldebugview.cpp b/linden/indra/newview/lldebugview.cpp index dc179cc..861a5bb 100644 --- a/linden/indra/newview/lldebugview.cpp +++ b/linden/indra/newview/lldebugview.cpp @@ -37,7 +37,6 @@ #include "llconsole.h" #include "lltextureview.h" #include "llresmgr.h" -#include "llaudiostatus.h" #include "imageids.h" #include "llvelocitybar.h" #include "llviewerwindow.h" @@ -109,19 +108,6 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) mStatViewp->setVisible(FALSE); addChild(mStatViewp); - // - // Audio debugging stuff - // - const S32 AUDIO_STATUS_LEFT = rect.getWidth()/2-100; - const S32 AUDIO_STATUS_WIDTH = 320; - const S32 AUDIO_STATUS_TOP = (rect.getHeight()/2)+400; - const S32 AUDIO_STATUS_HEIGHT = 320; - r.setLeftTopAndSize( AUDIO_STATUS_LEFT, AUDIO_STATUS_TOP, AUDIO_STATUS_WIDTH, AUDIO_STATUS_HEIGHT ); - LLAudiostatus* gAudioStatus = new LLAudiostatus("AudioStatus", r); - gAudioStatus->setFollowsTop(); - gAudioStatus->setFollowsRight(); - addChild(gAudioStatus); - const S32 VELOCITY_LEFT = 10; // 370; const S32 VELOCITY_WIDTH = 500; const S32 VELOCITY_TOP = 140; diff --git a/linden/indra/newview/lldrawable.h b/linden/indra/newview/lldrawable.h index c2cafe3..e550142 100644 --- a/linden/indra/newview/lldrawable.h +++ b/linden/indra/newview/lldrawable.h @@ -46,6 +46,7 @@ #include "llviewerobject.h" #include "llrect.h" +class LLCamera; class LLDrawPool; class LLDrawable; class LLFace; diff --git a/linden/indra/newview/lldrawpoolsky.h b/linden/indra/newview/lldrawpoolsky.h index 2f11c67..645e669 100644 --- a/linden/indra/newview/lldrawpoolsky.h +++ b/linden/indra/newview/lldrawpoolsky.h @@ -57,7 +57,7 @@ public: /*virtual*/ void render(S32 pass = 0); /*virtual*/ void renderForSelect(); void setSkyTex(LLSkyTex* const st) { mSkyTex = st; } - void setSun(LLHeavenBody* sun) { mHB[0] = sun; } + void setSun(LLHeavenBody* sun_flag) { mHB[0] = sun_flag; } void setMoon(LLHeavenBody* moon) { mHB[1] = moon; } void renderSkyCubeFace(U8 side); diff --git a/linden/indra/newview/lldrawpoolwater.cpp b/linden/indra/newview/lldrawpoolwater.cpp index 343f14c..100eb43 100644 --- a/linden/indra/newview/lldrawpoolwater.cpp +++ b/linden/indra/newview/lldrawpoolwater.cpp @@ -595,7 +595,7 @@ void LLDrawPoolWater::shade() glUniform1fARB(gWaterProgram.mUniform[LLShaderMgr::WATER_TIME], sTime); glUniform3fvARB(gWaterProgram.mUniform[LLShaderMgr::WATER_SPECULAR], 1, light_diffuse.mV); glUniform1fARB(gWaterProgram.mUniform[LLShaderMgr::WATER_SPECULAR_EXP], light_exp); - glUniform3fvARB(gWaterProgram.mUniform[LLShaderMgr::WATER_EYEVEC], 1, gCamera->getOrigin().mV); + glUniform3fvARB(gWaterProgram.mUniform[LLShaderMgr::WATER_EYEVEC], 1, (GLfloat *)(gCamera->getOrigin().mV)); glUniform2fvARB(gWaterProgram.mUniform[LLShaderMgr::WATER_WAVE_DIR1], 1, d1.mV); glUniform2fvARB(gWaterProgram.mUniform[LLShaderMgr::WATER_WAVE_DIR2], 1, d2.mV); glUniform3fvARB(gWaterProgram.mUniform[LLShaderMgr::WATER_LIGHT_DIR], 1, light_dir.mV); diff --git a/linden/indra/newview/llemote.h b/linden/indra/newview/llemote.h index a0aa353..9e2e09c 100644 --- a/linden/indra/newview/llemote.h +++ b/linden/indra/newview/llemote.h @@ -108,6 +108,8 @@ public: // called when a motion is deactivated virtual void onDeactivate(); + virtual BOOL canDeprecate() { return FALSE; } + static BOOL getIndexFromName( const char* name, U32* index ); protected: diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h index 711cd8e..24ef213 100644 --- a/linden/indra/newview/llface.h +++ b/linden/indra/newview/llface.h @@ -41,7 +41,6 @@ #include "lldarrayptr.h" #include "llvertexbuffer.h" #include "llviewerimage.h" -#include "llpagemem.h" #include "llstat.h" #include "lldrawable.h" diff --git a/linden/indra/newview/llfasttimerview.cpp b/linden/indra/newview/llfasttimerview.cpp index c7be3aa..ba1296a 100644 --- a/linden/indra/newview/llfasttimerview.cpp +++ b/linden/indra/newview/llfasttimerview.cpp @@ -931,8 +931,7 @@ void LLFastTimerView::draw() //draw line graph history { LLGLSNoTexture no_texture; - LLGLEnable scissor(GL_SCISSOR_TEST); - LLUI::setScissorRegionLocal(graph_rect); + LLLocalClipRect clip(graph_rect); //normalize based on last frame's maximum static U64 last_max = 0; diff --git a/linden/indra/newview/llfeaturemanager.cpp b/linden/indra/newview/llfeaturemanager.cpp index 2a30680..8bcbc1e 100644 --- a/linden/indra/newview/llfeaturemanager.cpp +++ b/linden/indra/newview/llfeaturemanager.cpp @@ -62,6 +62,8 @@ extern void write_debug(const std::string& str); const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt"; #elif LL_LINUX const char FEATURE_TABLE_FILENAME[] = "featuretable_linux.txt"; +#elif LL_SOLARIS +const char FEATURE_TABLE_FILENAME[] = "featuretable_solaris.txt"; #else const char FEATURE_TABLE_FILENAME[] = "featuretable.txt"; #endif @@ -405,7 +407,12 @@ void LLFeatureManager::initCPUFeatureMasks() maskFeatures("RAM256MB"); } +#if LL_SOLARIS && defined(__sparc) // even low MHz SPARCs are fast +#error The 800 is hinky. Would something like a LL_MIN_MHZ make more sense here? + if (gSysCPU.getMhz() < 800) +#else if (gSysCPU.getMhz() < 1100) +#endif { maskFeatures("CPUSlow"); } diff --git a/linden/indra/newview/llfirstuse.cpp b/linden/indra/newview/llfirstuse.cpp index 1ddac8e..b6bd444 100644 --- a/linden/indra/newview/llfirstuse.cpp +++ b/linden/indra/newview/llfirstuse.cpp @@ -35,6 +35,7 @@ // viewer includes #include "llnotify.h" +#include "llfloatervoicewizard.h" #include "llviewercontrol.h" #include "llui.h" #include "viewer.h" @@ -248,3 +249,15 @@ void LLFirstUse::useSculptedPrim() } } + +// static +void LLFirstUse::useVoice() +{ + if (gDisableVoice) return; + if (gSavedSettings.getWarning("FirstVoice")) + { + gSavedSettings.setWarning("FirstVoice", FALSE); + + LLFloaterVoiceWizard::showInstance(); + } +} diff --git a/linden/indra/newview/llfirstuse.h b/linden/indra/newview/llfirstuse.h index d48ae96..1edbf70 100644 --- a/linden/indra/newview/llfirstuse.h +++ b/linden/indra/newview/llfirstuse.h @@ -101,6 +101,7 @@ public: static void useFlexible(); static void useDebugMenus(); static void useSculptedPrim(); + static void useVoice(); protected: static std::set sConfigVariables; diff --git a/linden/indra/newview/llfloateractivespeakers.cpp b/linden/indra/newview/llfloateractivespeakers.cpp new file mode 100644 index 0000000..1c3990e --- /dev/null +++ b/linden/indra/newview/llfloateractivespeakers.cpp @@ -0,0 +1,831 @@ +/** + * @file llfloateractivespeakers.cpp + * @brief Management interface for muting and controlling volume of residents currently speaking + * + * Copyright (c) 2005-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloateractivespeakers.h" + +#include "llagent.h" +#include "llvoavatar.h" +#include "llfloateravatarinfo.h" +#include "llvieweruictrlfactory.h" +#include "llviewercontrol.h" +#include "llscrolllistctrl.h" +#include "llbutton.h" +#include "lltextbox.h" +#include "llmutelist.h" +#include "llviewerobjectlist.h" +#include "llimpanel.h" // LLVoiceChannel +#include "llsdutil.h" + +const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers +const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); +const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); +const F32 TYPING_ANIMATION_FPS = 2.5f; + +LLLocalSpeakerMgr* gLocalSpeakerMgr = NULL; +LLActiveSpeakerMgr* gActiveChannelSpeakerMgr = NULL; + +LLSpeaker::speaker_map_t LLSpeaker::sSpeakers; + +LLSpeaker::LLSpeaker(const LLUUID& id, const LLString& name, const ESpeakerType type) : + mStatus(LLSpeaker::STATUS_TEXT_ONLY), + mLastSpokeTime(0.f), + mSpeechVolume(0.f), + mHasSpoken(FALSE), + mDotColor(LLColor4::white), + mID(id), + mTyping(FALSE), + mSortIndex(0), + mType(type) +{ + mHandle.init(); + sSpeakers.insert(std::make_pair(mHandle, this)); + if (name.empty() && type == SPEAKER_AGENT) + { + lookupName(); + } + else + { + mDisplayName = name; + } + mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); +} + +LLSpeaker::~LLSpeaker() +{ + sSpeakers.erase(mHandle); +} + +void LLSpeaker::lookupName() +{ + gCacheName->getName(mID, onAvatarNameLookup, new LLViewHandle(mHandle)); +} + +//static +void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* user_data) +{ + LLViewHandle speaker_handle = *(LLViewHandle*)user_data; + delete (LLViewHandle*)user_data; + + speaker_map_t::iterator found_it = sSpeakers.find(speaker_handle); + if (found_it != sSpeakers.end()) + { + LLSpeaker* speakerp = found_it->second; + if (speakerp) + { + speakerp->mDisplayName = llformat("%s %s", first, last); + } + } +} + + +// helper sort class +struct LLSortRecentSpeakers +{ + bool operator()(const LLPointer lhs, const LLPointer rhs) const; +}; + +bool LLSortRecentSpeakers::operator()(const LLPointer lhs, const LLPointer rhs) const +{ + // Sort first on status + if (lhs->mStatus != rhs->mStatus) + { + return (lhs->mStatus < rhs->mStatus); + } + + // and then on last speaking time + if(lhs->mLastSpokeTime != rhs->mLastSpokeTime) + { + return (lhs->mLastSpokeTime > rhs->mLastSpokeTime); + } + + // and finally (only if those are both equal), on name. + return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 ); +} + +LLFloaterActiveSpeakers::LLFloaterActiveSpeakers(const LLSD& seed) : mPanel(NULL) +{ + mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL); + // do not automatically open singleton floaters (as result of getInstance()) + BOOL no_open = FALSE; + gUICtrlFactory->buildFloater(this, "floater_active_speakers.xml", &getFactoryMap(), no_open); + //RN: for now, we poll voice client every frame to get voice amplitude feedback + //gVoiceClient->addObserver(this); + mPanel->refreshSpeakers(); +} + +LLFloaterActiveSpeakers::~LLFloaterActiveSpeakers() +{ +} + +void LLFloaterActiveSpeakers::onClose(bool app_quitting) +{ + setVisible(FALSE); +} + +void LLFloaterActiveSpeakers::draw() +{ + // update state every frame to get live amplitude feedback + mPanel->refreshSpeakers(); + LLFloater::draw(); +} + +BOOL LLFloaterActiveSpeakers::postBuild() +{ + mPanel = (LLPanelActiveSpeakers*)LLUICtrlFactory::getPanelByName(this, "active_speakers_panel"); + return TRUE; +} + +void LLFloaterActiveSpeakers::onChange() +{ + //refresh(); +} + +//static +void* LLFloaterActiveSpeakers::createSpeakersPanel(void* data) +{ + // don't show text only speakers + return new LLPanelActiveSpeakers(gActiveChannelSpeakerMgr, FALSE); +} + + +// +// LLPanelActiveSpeakers +// +LLPanelActiveSpeakers::LLPanelActiveSpeakers(LLSpeakerMgr* data_source, BOOL show_text_chatters) : + mSpeakerList(NULL), + mMuteVoiceCtrl(NULL), + mMuteTextCtrl(NULL), + mNameText(NULL), + mProfileBtn(NULL), + mShowTextChatters(show_text_chatters), + mSpeakerMgr(data_source) +{ + setMouseOpaque(FALSE); +} + +LLPanelActiveSpeakers::~LLPanelActiveSpeakers() +{ + +} + +BOOL LLPanelActiveSpeakers::postBuild() +{ + mSpeakerList = LLUICtrlFactory::getScrollListByName(this, "speakers_list"); + + mMuteTextCtrl = (LLUICtrl*)getCtrlByNameAndType("mute_text_btn", WIDGET_TYPE_DONTCARE); + childSetCommitCallback("mute_text_btn", onClickMuteTextCommit, this); + + mMuteVoiceCtrl = (LLUICtrl*)getCtrlByNameAndType("mute_btn", WIDGET_TYPE_DONTCARE); + childSetCommitCallback("mute_btn", onClickMuteVoiceCommit, this); + childSetAction("mute_btn", onClickMuteVoice, this); + + childSetCommitCallback("speaker_volume", onVolumeChange, this); + + mNameText = LLUICtrlFactory::getTextBoxByName(this, "resident_name"); + + mProfileBtn = LLUICtrlFactory::getButtonByName(this, "profile_btn"); + childSetAction("profile_btn", onClickProfile, this); + return TRUE; +} + +void LLPanelActiveSpeakers::refreshSpeakers() +{ + // store off current selection and scroll state to preserve across list rebuilds + LLUUID selected_id = mSpeakerList->getSimpleSelectedValue().asUUID(); + S32 scroll_pos = mSpeakerList->getScrollInterface()->getScrollPos(); + + BOOL sort_ascending = mSpeakerList->getSortAscending(); + LLString sort_column = mSpeakerList->getSortColumnName(); + // TODO: put this in xml + // enforces default sort column of speaker status + if (sort_column.empty()) + { + sort_column = "speaking_status"; + } + + mSpeakerMgr->update(); + + // clear scrolling list widget of names + mSpeakerList->clearRows(); + + LLSpeakerMgr::speaker_list_t speaker_list; + mSpeakerMgr->getSpeakerList(&speaker_list, mShowTextChatters); + for (LLSpeakerMgr::speaker_list_t::const_iterator speaker_it = speaker_list.begin(); speaker_it != speaker_list.end(); ++speaker_it) + { + LLUUID speaker_id = (*speaker_it)->mID; + LLPointer speakerp = (*speaker_it); + + // since we are forced to sort by text, encode sort order as string + LLString speaking_order_sort_string = llformat("%010d", speakerp->mSortIndex); + + LLSD row; + row["id"] = speaker_id; + + row["columns"][0]["column"] = "icon_speaking_status"; + row["columns"][0]["type"] = "icon"; + row["columns"][0]["color"] = speakerp->mDotColor.getValue(); + LLString icon_image_id; + + S32 icon_image_idx = llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); + switch(icon_image_idx) + { + case 0: + icon_image_id = gViewerArt.getString("icn_active-speakers-dot-lvl0.tga"); + break; + case 1: + icon_image_id = gViewerArt.getString("icn_active-speakers-dot-lvl1.tga"); + break; + case 2: + icon_image_id = gViewerArt.getString("icn_active-speakers-dot-lvl2.tga"); + break; + } + //if (speakerp->mTyping) + //{ + // S32 typing_anim_idx = llround(mIconAnimationTimer.getElapsedTimeF32() * TYPING_ANIMATION_FPS) % 3; + // switch(typing_anim_idx) + // { + // case 0: + // row["columns"][0]["overlay"] = LLUUID(gViewerArt.getString("icn_active-speakers-typing1.tga")); + // break; + // case 1: + // row["columns"][0]["overlay"] = LLUUID(gViewerArt.getString("icn_active-speakers-typing2.tga")); + // break; + // case 2: + // row["columns"][0]["overlay"] = LLUUID(gViewerArt.getString("icn_active-speakers-typing3.tga")); + // break; + // default: + // break; + // } + //} + + row["columns"][0]["value"] = speakerp->mStatus == LLSpeaker::STATUS_MUTED ? + gViewerArt.getString("mute_icon.tga") : icon_image_id; + if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE) // if voice is disabled for this speaker + { + // non voice speakers have hidden icons, render as transparent + row["columns"][0]["color"] = LLColor4(0.f, 0.f, 0.f, 0.f).getValue(); + } + row["columns"][1]["column"] = "speaker_name"; + row["columns"][1]["type"] = "text"; + if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL) + { + // draw inactive speakers in gray + row["columns"][1]["color"] = LLColor4::grey4.getValue(); + } + + if (speakerp->mDisplayName.empty()) + { + row["columns"][1]["value"] = LLCacheName::getDefaultName(); + } + else + { + row["columns"][1]["value"] = speakerp->mDisplayName; + } + + row["columns"][2]["column"] = "speaking_status"; + row["columns"][2]["type"] = "text"; + + // print speaking ordinal in a text-sorting friendly manner + row["columns"][2]["value"] = speaking_order_sort_string; + + mSpeakerList->addElement(row); + } + + //restore sort order, selection, etc + mSpeakerList->sortByColumn(sort_column, sort_ascending); + // make sure something is selected + if (selected_id.isNull()) + { + mSpeakerList->selectFirstItem(); + } + else + { + mSpeakerList->selectByValue(selected_id); + } + + LLPointer speakerp = mSpeakerMgr->findSpeaker(selected_id); + + if (gMuteListp) + { + // update UI for selected participant + if (mMuteVoiceCtrl) + { + mMuteVoiceCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagVoiceChat)); + mMuteVoiceCtrl->setEnabled(selected_id.notNull() + && selected_id != gAgent.getID() + && mSpeakerMgr->isVoiceActive() + && (speakerp.notNull() && speakerp->mType == LLSpeaker::SPEAKER_AGENT)); + } + if (mMuteTextCtrl) + { + mMuteTextCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagTextChat)); + mMuteTextCtrl->setEnabled(selected_id.notNull() && selected_id != gAgent.getID() && speakerp.notNull() && !gMuteListp->isLinden(speakerp->mDisplayName)); + } + childSetValue("speaker_volume", gVoiceClient->getUserVolume(selected_id)); + childSetEnabled("speaker_volume", selected_id.notNull() + && selected_id != gAgent.getID() + && mSpeakerMgr->isVoiceActive() + && (speakerp.notNull() && speakerp->mType == LLSpeaker::SPEAKER_AGENT)); + if (mProfileBtn) + { + mProfileBtn->setEnabled(selected_id.notNull()); + } + } + + // show selected user name in large font + if (mNameText) + { + if (speakerp) + { + mNameText->setValue(speakerp->mDisplayName); + } + else + { + mNameText->setValue(""); + } + } + + // keep scroll value stable + mSpeakerList->getScrollInterface()->setScrollPos(scroll_pos); +} + +void LLPanelActiveSpeakers::setSpeaker(const LLUUID& id, const LLString& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) +{ + mSpeakerMgr->setSpeaker(id, name, status, type); +} + + +//static +void LLPanelActiveSpeakers::onClickMuteTextCommit(LLUICtrl* ctrl, void* user_data) +{ + LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; + LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); + BOOL is_muted = gMuteListp->isMuted(speaker_id, LLMute::flagTextChat); + std::string name; + + //fill in name using voice client's copy of name cache + LLPointer speakerp = panelp->mSpeakerMgr->findSpeaker(speaker_id); + if (speakerp.isNull()) + { + return; + } + + name = speakerp->mDisplayName; + + LLMute mute(speaker_id, name, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT); + + if (!is_muted) + { + gMuteListp->add(mute, LLMute::flagTextChat); + } + else + { + gMuteListp->remove(mute, LLMute::flagTextChat); + } +} + +//static +void LLPanelActiveSpeakers::onClickMuteVoice(void* user_data) +{ + onClickMuteVoiceCommit(NULL, user_data); +} + +//static +void LLPanelActiveSpeakers::onClickMuteVoiceCommit(LLUICtrl* ctrl, void* user_data) +{ + LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; + LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); + BOOL is_muted = gMuteListp->isMuted(speaker_id, LLMute::flagVoiceChat); + std::string name; + + LLPointer speakerp = panelp->mSpeakerMgr->findSpeaker(speaker_id); + if (speakerp.isNull()) + { + return; + } + + name = speakerp->mDisplayName; + + // muting voice means we're dealing with an agent + LLMute mute(speaker_id, name, LLMute::AGENT); + + if (!is_muted) + { + gMuteListp->add(mute, LLMute::flagVoiceChat); + } + else + { + gMuteListp->remove(mute, LLMute::flagVoiceChat); + } +} + + +//static +void LLPanelActiveSpeakers::onVolumeChange(LLUICtrl* source, void* user_data) +{ + LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; + LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); + + gVoiceClient->setUserVolume(speaker_id, (F32)panelp->childGetValue("speaker_volume").asReal()); +} + +//static +void LLPanelActiveSpeakers::onClickProfile(void* user_data) +{ + LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; + LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); + + LLFloaterAvatarInfo::showFromDirectory(speaker_id); +} + +// +// LLSpeakerMgr +// + +LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : + mVoiceChannel(channelp) +{ +} + +LLSpeakerMgr::~LLSpeakerMgr() +{ +} + +LLPointer LLSpeakerMgr::setSpeaker(const LLUUID& id, const LLString& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) +{ + if (id.isNull()) return NULL; + + LLPointer speakerp; + if (mSpeakers.find(id) == mSpeakers.end()) + { + speakerp = new LLSpeaker(id, name, type); + speakerp->mStatus = status; + mSpeakers.insert(std::make_pair(speakerp->mID, speakerp)); + mSpeakersSorted.push_back(speakerp); + } + else + { + speakerp = findSpeaker(id); + if (speakerp.notNull()) + { + // keep highest priority status (lowest value) instead of overriding current value + speakerp->mStatus = llmin(speakerp->mStatus, status); + speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + // RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id + // we need to override speakers that we think are objects when we find out they are really + // residents + if (type == LLSpeaker::SPEAKER_AGENT) + { + speakerp->mType = LLSpeaker::SPEAKER_AGENT; + speakerp->lookupName(); + } + } + } + + return speakerp; +} + +void LLSpeakerMgr::update() +{ + if (!gVoiceClient) + { + return; + } + + LLColor4 speaking_color = gSavedSettings.getColor4("SpeakingColor"); + LLColor4 overdriven_color = gSavedSettings.getColor4("OverdrivenColor"); + + updateSpeakerList(); + + // update status of all current speakers + BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()); + for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();) + { + LLUUID speaker_id = speaker_it->first; + LLSpeaker* speakerp = speaker_it->second; + + speaker_map_t::iterator cur_speaker_it = speaker_it++; + + if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id)) + { + speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id); + + if (gVoiceClient->getOnMuteList(speaker_id)) + { + speakerp->mStatus = LLSpeaker::STATUS_MUTED; + speakerp->mDotColor = LLColor4::white; + } + else if (gVoiceClient->getIsSpeaking(speaker_id)) + { + // reset inactivity expiration + if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING) + { + speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); + speakerp->mHasSpoken = TRUE; + } + speakerp->mStatus = LLSpeaker::STATUS_SPEAKING; + // interpolate between active color and full speaking color based on power of speech output + speakerp->mDotColor = speaking_color; + if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL) + { + speakerp->mDotColor = overdriven_color; + } + } + else + { + speakerp->mSpeechVolume = 0.f; + speakerp->mDotColor = ACTIVE_COLOR; + + if (speakerp->mHasSpoken) + { + // have spoken once, not currently speaking + speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN; + } + else + { + // default state for being in voice channel + speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE; + } + } + } + // speaker no longer registered in voice channel, demote to text only + else if (speakerp->mStatus != LLSpeaker::STATUS_NOT_IN_CHANNEL) + { + speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY; + speakerp->mSpeechVolume = 0.f; + speakerp->mDotColor = ACTIVE_COLOR; + } + } + + // sort by status then time last spoken + std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers()); + + // for recent speakers who are not currently speaking, show "recent" color dot for most recent + // fading to "active" color + + S32 recent_speaker_count = 0; + S32 sort_index = 0; + speaker_list_t::iterator sorted_speaker_it; + for(sorted_speaker_it = mSpeakersSorted.begin(); + sorted_speaker_it != mSpeakersSorted.end(); ) + { + LLPointer speakerp = *sorted_speaker_it; + + // color code recent speakers who are not currently speaking + if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN) + { + speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f)); + recent_speaker_count++; + } + + // stuff sort ordinal into speaker so the ui can sort by this value + speakerp->mSortIndex = sort_index++; + + // remove speakers that have been gone too long + if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired()) + { + mSpeakers.erase(speakerp->mID); + sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it); + } + else + { + ++sorted_speaker_it; + } + } +} + +void LLSpeakerMgr::updateSpeakerList() +{ + // are we bound to the currently active voice channel? + if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive())) + { + LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList(); + LLVoiceClient::participantMap::iterator participant_it; + + // add new participants to our list of known speakers + for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it) + { + LLVoiceClient::participantState* participantp = participant_it->second; + setSpeaker(participantp->mAvatarID, "", LLSpeaker::STATUS_VOICE_ACTIVE); + } + } +} + +const LLPointer LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id) +{ + speaker_map_t::iterator found_it = mSpeakers.find(speaker_id); + if (found_it == mSpeakers.end()) + { + return NULL; + } + return found_it->second; +} + +void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text) +{ + speaker_list->clear(); + for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) + { + LLPointer speakerp = speaker_it->second; + // what about text only muted or inactive? + if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY) + { + speaker_list->push_back(speakerp); + } + } +} + +void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing) +{ + LLPointer speakerp = findSpeaker(speaker_id); + if (speakerp.notNull()) + { + speakerp->mTyping = typing; + } +} + +// speaker has chatted via either text or voice +void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id) +{ + LLPointer speakerp = findSpeaker(speaker_id); + if (speakerp.notNull()) + { + speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32(); + speakerp->mHasSpoken = TRUE; + } +} + +BOOL LLSpeakerMgr::isVoiceActive() +{ + // mVoiceChannel = NULL means current voice channel, whatever it is + return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive(); +} + + +// +// LLIMSpeakerMgr +// +LLIMSpeakerMgr::LLIMSpeakerMgr(LLVoiceChannel* channel) : LLSpeakerMgr(channel) +{ +} + +void LLIMSpeakerMgr::updateSpeakerList() +{ + // don't do normal updates which are pulled from voice channel + // rely on user list reported by sim + return; +} + +void LLIMSpeakerMgr::processSpeakerList(LLSD list) +{ + for(LLSD::array_iterator list_it = list.beginArray(); + list_it != list.endArray(); + ++list_it) + { + LLUUID agent_id(list_it->asUUID()); + + setSpeaker(agent_id, "", LLSpeaker::STATUS_TEXT_ONLY); + } +} + +void LLIMSpeakerMgr::processSpeakerMap(LLSD map) +{ + for(LLSD::map_iterator map_it = map.beginMap(); + map_it != map.endMap(); + ++map_it) + { + // add as new speaker + setSpeaker(LLUUID(map_it->first)); + } +} + + + +void LLIMSpeakerMgr::processSpeakerListUpdate(LLSD update) +{ + for(LLSD::map_iterator update_it = update.beginMap(); + update_it != update.endMap(); + ++update_it) + { + LLUUID agent_id(update_it->first); + + if (update_it->second.asString() == "LEAVE") + { + LLPointer speakerp = findSpeaker(agent_id); + if (speakerp) + { + speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; + speakerp->mDotColor = INACTIVE_COLOR; + speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + } + } + else if (update_it->second.asString() == "ENTER") + { + // add or update speaker + setSpeaker(agent_id); + } + else + { + llwarns << "LLIMSpeakerMgr::processSpeakerListUpdate() : bad membership list update " << ll_print_sd(update_it->second) << llendl; + } + } +} + + +// +// LLActiveSpeakerMgr +// + +LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL) +{ +} + +void LLActiveSpeakerMgr::updateSpeakerList() +{ + // point to whatever the current voice channel is + mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel(); + + // always populate from active voice channel + if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) + { + mSpeakers.clear(); + mSpeakersSorted.clear(); + mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel(); + } + LLSpeakerMgr::updateSpeakerList(); +} + + + +// +// LLLocalSpeakerMgr +// + +LLLocalSpeakerMgr::LLLocalSpeakerMgr() : LLSpeakerMgr(LLVoiceChannelProximal::getInstance()) +{ +} + +LLLocalSpeakerMgr::~LLLocalSpeakerMgr () +{ +} + +void LLLocalSpeakerMgr::updateSpeakerList() +{ + // pull speakers from voice channel + LLSpeakerMgr::updateSpeakerList(); + + // add non-voice speakers in chat range + std::vector< LLCharacter* >::iterator avatar_it; + for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it) + { + LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it; + if (dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) <= CHAT_NORMAL_RADIUS) + { + setSpeaker(avatarp->getID()); + } + } + + // check if text only speakers have moved out of chat range + for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) + { + LLUUID speaker_id = speaker_it->first; + LLSpeaker* speakerp = speaker_it->second; + if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) + { + LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id); + if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS) + { + speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; + speakerp->mDotColor = INACTIVE_COLOR; + speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + } + } + } +} diff --git a/linden/indra/newview/llfloateractivespeakers.h b/linden/indra/newview/llfloateractivespeakers.h new file mode 100644 index 0000000..f24eca4 --- /dev/null +++ b/linden/indra/newview/llfloateractivespeakers.h @@ -0,0 +1,211 @@ +/** + * @file llfloateractivespeakers.h + * @brief Management interface for muting and controlling volume of residents currently speaking + * + * Copyright (c) 2005-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LL_LLFLOATERACTIVESPEAKERS_H +#define LL_LLFLOATERACTIVESPEAKERS_H + +#include "llfloater.h" +#include "llmemory.h" +#include "llvoiceclient.h" +#include "llframetimer.h" + +class LLScrollListCtrl; +class LLButton; +class LLPanelActiveSpeakers; +class LLSpeakerMgr; +class LLVoiceChannel; + + +// data for a given participant in a voice channel +class LLSpeaker : public LLRefCount +{ +public: + typedef enum e_speaker_type + { + SPEAKER_AGENT, + SPEAKER_OBJECT + } ESpeakerType; + + typedef enum e_speaker_status + { + STATUS_SPEAKING, + STATUS_HAS_SPOKEN, + STATUS_VOICE_ACTIVE, + STATUS_TEXT_ONLY, + STATUS_NOT_IN_CHANNEL, + STATUS_MUTED + } ESpeakerStatus; + + + LLSpeaker(const LLUUID& id, const LLString& name = LLString::null, const ESpeakerType type = SPEAKER_AGENT); + ~LLSpeaker(); + + void lookupName(); + + static void onAvatarNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* user_data); + +public: + + ESpeakerStatus mStatus; // current activity status in speech group + F32 mLastSpokeTime; // timestamp when this speaker last spoke + F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?) + LLString mDisplayName; // cache user name for this speaker + LLFrameTimer mActivityTimer; // time out speakers when they are not part of current voice channel + BOOL mHasSpoken; // has this speaker said anything this session? + LLColor4 mDotColor; + LLUUID mID; + BOOL mTyping; + S32 mSortIndex; + LLViewHandle mHandle; + ESpeakerType mType; + + typedef std::map speaker_map_t; + static speaker_map_t sSpeakers; +}; + +class LLSpeakerMgr +{ +public: + LLSpeakerMgr(LLVoiceChannel* channelp); + virtual ~LLSpeakerMgr(); + + const LLPointer findSpeaker(const LLUUID& avatar_id); + void update(); + void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing); + void speakerChatted(const LLUUID& speaker_id); + LLPointer setSpeaker(const LLUUID& id, + const LLString& name = LLString::null, + LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY, + LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT); + + BOOL isVoiceActive(); + + typedef std::vector > speaker_list_t; + void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text); + +protected: + virtual void updateSpeakerList(); + + typedef std::map > speaker_map_t; + speaker_map_t mSpeakers; + + speaker_list_t mSpeakersSorted; + LLFrameTimer mSpeechTimer; + LLVoiceChannel* mVoiceChannel; +}; + +class LLIMSpeakerMgr : public LLSpeakerMgr +{ +public: + LLIMSpeakerMgr(LLVoiceChannel* channel); + + void processSpeakerListUpdate(LLSD update); + void processSpeakerList(LLSD list); + void processSpeakerMap(LLSD list); +protected: + virtual void updateSpeakerList(); +}; + +class LLActiveSpeakerMgr : public LLSpeakerMgr +{ +public: + LLActiveSpeakerMgr(); +protected: + virtual void updateSpeakerList(); +}; + +class LLLocalSpeakerMgr : public LLSpeakerMgr +{ +public: + LLLocalSpeakerMgr(); + ~LLLocalSpeakerMgr (); +protected: + virtual void updateSpeakerList(); +}; + + +class LLFloaterActiveSpeakers : + public LLUISingleton, + public LLFloater, + public LLVoiceClientParticipantObserver +{ + // friend of singleton class to allow construction inside getInstance() since constructor is protected + // to enforce singleton constraint + friend class LLUISingleton; +public: + virtual ~LLFloaterActiveSpeakers(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void draw(); + + /*virtual*/ void onChange(); + + static void* createSpeakersPanel(void* data); + +protected: + LLFloaterActiveSpeakers(const LLSD& seed); + + LLPanelActiveSpeakers* mPanel; +}; + +class LLPanelActiveSpeakers : public LLPanel +{ +public: + LLPanelActiveSpeakers(LLSpeakerMgr* data_source, BOOL show_text_chatters); + virtual ~LLPanelActiveSpeakers(); + + /*virtual*/ BOOL postBuild(); + + void refreshSpeakers(); + + void setSpeaker(const LLUUID& id, + const LLString& name = LLString::null, + LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY, + LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT); + + static void onClickMuteVoice(void* user_data); + static void onClickMuteVoiceCommit(LLUICtrl* ctrl, void* user_data); + static void onClickMuteTextCommit(LLUICtrl* ctrl, void* user_data); + static void onVolumeChange(LLUICtrl* source, void* user_data); + static void onClickProfile(void* user_data); +protected: + LLScrollListCtrl* mSpeakerList; + LLUICtrl* mMuteVoiceCtrl; + LLUICtrl* mMuteTextCtrl; + LLTextBox* mNameText; + LLButton* mProfileBtn; + BOOL mShowTextChatters; + LLSpeakerMgr* mSpeakerMgr; + LLFrameTimer mIconAnimationTimer; +}; + +extern LLLocalSpeakerMgr* gLocalSpeakerMgr; +extern LLActiveSpeakerMgr* gActiveChannelSpeakerMgr; + +#endif // LL_LLFLOATERACTIVESPEAKERS_H diff --git a/linden/indra/newview/llfloateranimpreview.cpp b/linden/indra/newview/llfloateranimpreview.cpp index b1f8a53..09fc508 100644 --- a/linden/indra/newview/llfloateranimpreview.cpp +++ b/linden/indra/newview/llfloateranimpreview.cpp @@ -993,7 +993,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata) LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID); } - floaterp->onClose(false); + floaterp->close(false); } //----------------------------------------------------------------------------- diff --git a/linden/indra/newview/llfloateravatarpicker.cpp b/linden/indra/newview/llfloateravatarpicker.cpp index 6989084..3bb2462 100644 --- a/linden/indra/newview/llfloateravatarpicker.cpp +++ b/linden/indra/newview/llfloateravatarpicker.cpp @@ -208,7 +208,12 @@ void LLFloaterAvatarPicker::onSelectionChange(const std::dequemAvatarIDs.clear(); self->mAvatarNames.clear(); - self->childSetEnabled("Select", FALSE); + // if we have calling cards, disable select button until + // the inventory picks a valid calling card + if (!items.empty()) + { + self->childSetEnabled("Select", FALSE); + } if (!self->mListNames) { diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp index dd79afd..2621161 100644 --- a/linden/indra/newview/llfloaterchat.cpp +++ b/linden/indra/newview/llfloaterchat.cpp @@ -34,6 +34,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterchat.h" +#include "llfloateractivespeakers.h" #include "llfloaterscriptdebug.h" #include "llchat.h" @@ -49,11 +50,13 @@ #include "llcheckboxctrl.h" #include "llcombobox.h" #include "llconsole.h" +#include "llfloaterchatterbox.h" #include "llfloatermute.h" #include "llkeyboard.h" //#include "lllineeditor.h" #include "llmutelist.h" //#include "llresizehandle.h" +#include "llchatbar.h" #include "llstatusbar.h" #include "llviewertexteditor.h" #include "llviewergesture.h" // for triggering gestures @@ -70,7 +73,6 @@ // // Constants // -const char FLOATER_TITLE[] = "Chat History"; const F32 INSTANT_MSG_SIZE = 8.0f; const F32 CHAT_MSG_SIZE = 8.0f; const LLColor4 INSTANT_MSG_COLOR(1, 1, 1, 1); @@ -80,25 +82,25 @@ const S32 MAX_CHATTER_COUNT = 16; // // Global statics // -LLFloaterChat* gFloaterChat = NULL; - LLColor4 get_text_color(const LLChat& chat); // // Member Functions // -LLFloaterChat::LLFloaterChat() -: LLFloater("chat floater", "FloaterChatRect", FLOATER_TITLE, - RESIZE_YES, 440, 100, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES) +LLFloaterChat::LLFloaterChat(const LLSD& seed) +: LLFloater("chat floater", "FloaterChatRect", "", + RESIZE_YES, 440, 100, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES), + mPanel(NULL) { - - gUICtrlFactory->buildFloater(this,"floater_chat_history.xml"); + mFactoryMap["chat_panel"] = LLCallbackMap(createChatPanel, NULL); + mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL); + // do not automatically open singleton floaters (as result of getInstance()) + BOOL no_open = FALSE; + gUICtrlFactory->buildFloater(this,"floater_chat_history.xml",&getFactoryMap(),no_open); - childSetAction("Mute resident",onClickMute,this); - childSetAction("Chat", onClickChat, this); - childSetCommitCallback("chatter combobox",onCommitUserSelect,this); childSetCommitCallback("show mutes",onClickToggleShowMute,this); //show mutes childSetVisible("Chat History Editor with mute",FALSE); + childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this); setDefaultBtn("Chat"); } @@ -112,33 +114,53 @@ void LLFloaterChat::setVisible(BOOL visible) LLFloater::setVisible( visible ); gSavedSettings.setBOOL("ShowChatHistory", visible); +} - // Hide the chat overlay when our history is visible. - gConsole->setVisible( !visible ); +void LLFloaterChat::draw() +{ + // enable say and shout only when text available + + childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel")); + + LLChatBar* chat_barp = (LLChatBar*)getChildByName("chat_panel", TRUE); + if (chat_barp) + { + chat_barp->refresh(); + } + + mPanel->refreshSpeakers(); + LLFloater::draw(); } +BOOL LLFloaterChat::postBuild() +{ + mPanel = (LLPanelActiveSpeakers*)LLUICtrlFactory::getPanelByName(this, "active_speakers_panel"); + + LLChatBar* chat_barp = (LLChatBar*)getChildByName("chat_panel", TRUE); + if (chat_barp) + { + chat_barp->setGestureCombo(LLUICtrlFactory::getComboBoxByName(this, "Gesture")); + } + return TRUE; +} // public virtual void LLFloaterChat::onClose(bool app_quitting) { - LLFloater::setVisible( FALSE ); - if (!app_quitting) { gSavedSettings.setBOOL("ShowChatHistory", FALSE); } - - // Hide the chat overlay when our history is visible. - gConsole->setVisible( TRUE ); + setVisible(FALSE); } - -// public -void LLFloaterChat::show() +void LLFloaterChat::onVisibilityChange(BOOL new_visibility) { - open(); /*Flawfinder: ignore*/ + // Hide the chat overlay when our history is visible. + gConsole->setVisible( !new_visibility ); } + void add_timestamped_line(LLViewerTextEditor* edit, const LLString& line, const LLColor4& color) { bool prepend_newline = true; @@ -162,7 +184,7 @@ void log_chat_text(const LLChat& chat) } // static void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) -{ +{ if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file) { log_chat_text(chat); @@ -185,10 +207,9 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) } // could flash the chat button in the status bar here. JC - if (!gFloaterChat) return; - - LLViewerTextEditor* history_editor = (LLViewerTextEditor*)gFloaterChat->getChildByName("Chat History Editor"); - LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)gFloaterChat->getChildByName("Chat History Editor with mute"); + LLFloaterChat* chat_floater = LLFloaterChat::getInstance(LLSD()); + LLViewerTextEditor* history_editor = (LLViewerTextEditor*)chat_floater->getChildByName("Chat History Editor", TRUE); + LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)chat_floater->getChildByName("Chat History Editor with mute", TRUE); history_editor->setParseHTML(TRUE); history_editor_with_mute->setParseHTML(TRUE); @@ -204,77 +225,24 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f); add_timestamped_line(history_editor_with_mute, chat.mText, color); } - - if (!chat.mMuted - && chat.mSourceType != CHAT_SOURCE_SYSTEM - && chat.mFromID.notNull() - && chat.mFromID != gAgent.getID()) + + // add objects as transient speakers that can be muted + if (chat.mSourceType == CHAT_SOURCE_OBJECT) { - - LLComboBox* chatter_combo = LLUICtrlFactory::getComboBoxByName(gFloaterChat,"chatter combobox"); - - if(!chatter_combo) - { - return; - } - - if (!chatter_combo->setCurrentByID(chat.mFromID)) - { - // if we have too many items... - if (chatter_combo->getItemCount() >= MAX_CHATTER_COUNT) - { - chatter_combo->remove(0); - } - - LLMute mute(chat.mFromID, chat.mFromName); - if (chat.mSourceType == CHAT_SOURCE_OBJECT) - { - mute.mType = LLMute::OBJECT; - } - else if (chat.mSourceType == CHAT_SOURCE_AGENT) - { - mute.mType = LLMute::AGENT; - } - LLString item = mute.getDisplayName(); - chatter_combo->add(item, chat.mFromID); - chatter_combo->setCurrentByIndex(chatter_combo->getItemCount() - 1); - gFloaterChat->childSetEnabled("Mute resident",TRUE); - } + chat_floater->mPanel->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT); } } // static void LLFloaterChat::setHistoryCursorAndScrollToEnd() { - if (gFloaterChat) - { - LLViewerTextEditor* history_editor = (LLViewerTextEditor*)gFloaterChat->getChildByName("Chat History Editor"); - LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)gFloaterChat->getChildByName("Chat History Editor with mute"); - - history_editor->setCursorAndScrollToEnd(); - history_editor_with_mute->setCursorAndScrollToEnd(); - } -} - - -// static -void LLFloaterChat::toggle(void*) -{ - if (gFloaterChat->getVisible()) - { - gFloaterChat->close(); - } - else - { - gFloaterChat->show(); - } + LLViewerTextEditor* history_editor = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor", TRUE); + LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor with mute", TRUE); + + history_editor->setCursorAndScrollToEnd(); + history_editor_with_mute->setCursorAndScrollToEnd(); } -// static -BOOL LLFloaterChat::visible(void*) -{ - return (gFloaterChat && gFloaterChat->getVisible()); -} //static void LLFloaterChat::onClickMute(void *data) @@ -299,30 +267,6 @@ void LLFloaterChat::onClickMute(void *data) } //static -void LLFloaterChat::onClickChat(void*) -{ - // we need this function as a level of indirection because otherwise startChat would - // cast the data pointer to a character string, and dump garbage in the chat - LLChatBar::startChat(NULL); -} - -//static -void LLFloaterChat::onCommitUserSelect(LLUICtrl* caller, void* data) -{ - LLFloaterChat* floater = (LLFloaterChat*)data; - LLComboBox* combo = (LLComboBox*)caller; - - if (combo->getCurrentIndex() == -1) - { - floater->childSetEnabled("Mute resident",FALSE); - } - else - { - floater->childSetEnabled("Mute resident",TRUE); - } -} - -//static void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data) { LLFloaterChat* floater = (LLFloaterChat*)data; @@ -330,8 +274,8 @@ void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data) //LLCheckBoxCtrl* BOOL show_mute = LLUICtrlFactory::getCheckBoxByName(floater,"show mutes")->get(); - LLViewerTextEditor* history_editor = (LLViewerTextEditor*)floater->getChildByName("Chat History Editor"); - LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)floater->getChildByName("Chat History Editor with mute"); + LLViewerTextEditor* history_editor = (LLViewerTextEditor*)floater->getChildByName("Chat History Editor", TRUE); + LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)floater->getChildByName("Chat History Editor with mute", TRUE); if (!history_editor || !history_editor_with_mute) return; @@ -447,7 +391,7 @@ LLColor4 get_text_color(const LLChat& chat) //static void LLFloaterChat::loadHistory() { - LLLogChat::loadHistory("chat", &chatFromLogFile, (void *)gFloaterChat); + LLLogChat::loadHistory("chat", &chatFromLogFile, (void *)LLFloaterChat::getInstance(LLSD())); } //static @@ -458,3 +402,40 @@ void LLFloaterChat::chatFromLogFile(LLString line, void* userdata) chat.mText = line; addChatHistory(chat, FALSE); } + +//static +void* LLFloaterChat::createSpeakersPanel(void* data) +{ + return new LLPanelActiveSpeakers(gLocalSpeakerMgr, TRUE); +} + +//static +void* LLFloaterChat::createChatPanel(void* data) +{ + LLChatBar* chatp = new LLChatBar("floating_chat_bar"); + return chatp; +} + +//static +void LLFloaterChat::hideInstance(const LLSD& id) +{ + LLFloaterChat* floaterp = LLFloaterChat::getInstance(LLSD()); + // don't do anything when hosted in the chatterbox + if(floaterp->getHost()) + { + LLFloaterChatterBox::hideInstance(LLSD()); + } + else + { + LLUISingleton::hideInstance(id); + } +} + +// static +void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata) +{ + LLFloaterChat* self = (LLFloaterChat*)userdata; + + self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel")); +} + diff --git a/linden/indra/newview/llfloaterchat.h b/linden/indra/newview/llfloaterchat.h index 54df738..9558a65 100644 --- a/linden/indra/newview/llfloaterchat.h +++ b/linden/indra/newview/llfloaterchat.h @@ -44,17 +44,20 @@ class LLViewerTextEditor; class LLMessageSystem; class LLUUID; class LLCheckBoxCtrl; +class LLPanelActiveSpeakers; class LLFloaterChat -: public LLFloater +: public LLFloater, public LLUISingleton { public: - LLFloaterChat(); + LLFloaterChat(const LLSD& seed); ~LLFloaterChat(); - void show(); - virtual void onClose(bool app_quitting); virtual void setVisible( BOOL b ); + virtual void draw(); + virtual BOOL postBuild(); + virtual void onClose(bool app_quitting); + virtual void onVisibilityChange(BOOL cur_visibility); static void setHistoryCursorAndScrollToEnd(); @@ -65,17 +68,17 @@ public: // Add chat to history alone. static void addChatHistory(const LLChat& chat, bool log_to_file = true); - static void toggle(void*); - static BOOL visible(void*); - static void onClickMute(void *data); - static void onClickChat(void *); - static void onCommitUserSelect(LLUICtrl* caller, void* data); static void onClickToggleShowMute(LLUICtrl* caller, void *data); + static void onClickToggleActiveSpeakers(void* userdata); static void chatFromLogFile(LLString line, void* userdata); static void loadHistory(); -}; + static void* createSpeakersPanel(void* data); + static void* createChatPanel(void* data); + static void hideInstance(const LLSD& id); -extern LLFloaterChat* gFloaterChat; +protected: + LLPanelActiveSpeakers* mPanel; +}; #endif diff --git a/linden/indra/newview/llfloaterchatterbox.cpp b/linden/indra/newview/llfloaterchatterbox.cpp new file mode 100644 index 0000000..11d2ee6 --- /dev/null +++ b/linden/indra/newview/llfloaterchatterbox.cpp @@ -0,0 +1,342 @@ +/** + * @file llfloaterchatterbox.cpp + * @author Richard + * @date 2007-05-08 + * @brief Implementation of the chatterbox integrated conversation ui + * + * Copyright (c) 2007-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterchatterbox.h" +#include "llvieweruictrlfactory.h" +#include "llfloaterchat.h" +#include "llfloaterfriends.h" +#include "llfloatergroups.h" +#include "llviewercontrol.h" +#include "llimview.h" +#include "llimpanel.h" + +// +// LLFloaterMyFriends +// + +LLFloaterMyFriends::LLFloaterMyFriends(const LLSD& seed) +{ + mFactoryMap["friends_panel"] = LLCallbackMap(LLFloaterMyFriends::createFriendsPanel, NULL); + mFactoryMap["groups_panel"] = LLCallbackMap(LLFloaterMyFriends::createGroupsPanel, NULL); + // do not automatically open singleton floaters (as result of getInstance()) + BOOL no_open = FALSE; + gUICtrlFactory->buildFloater(this, "floater_my_friends.xml", &getFactoryMap(), no_open); +} + +LLFloaterMyFriends::~LLFloaterMyFriends() +{ +} + +BOOL LLFloaterMyFriends::postBuild() +{ + mTabs = LLUICtrlFactory::getTabContainerByName(this, "friends_and_groups"); + + return TRUE; +} + + +void LLFloaterMyFriends::onClose(bool app_quitting) +{ + setVisible(FALSE); +} + +//static +LLFloaterMyFriends* LLFloaterMyFriends::showInstance(const LLSD& id) +{ + LLFloaterMyFriends* floaterp = LLUIInstanceMgr::showInstance(id); + // garbage values in id will be interpreted as 0, or the friends tab + floaterp->mTabs->selectTab(id); + + return floaterp; +} + +//static +void LLFloaterMyFriends::hideInstance(const LLSD& id) +{ + if(instanceVisible(id)) + { + LLFloaterChatterBox::hideInstance(LLSD()); + } +} + +// is the specified panel currently visible +//static +BOOL LLFloaterMyFriends::instanceVisible(const LLSD& id) +{ + // if singleton not created yet, trivially return false + if (!findInstance(id)) return FALSE; + + LLFloaterMyFriends* floaterp = getInstance(id); + return floaterp->isInVisibleChain() && floaterp->mTabs->getCurrentPanelIndex() == id.asInteger(); +} + +//static +void* LLFloaterMyFriends::createFriendsPanel(void* data) +{ + return new LLPanelFriends(); +} + +//static +void* LLFloaterMyFriends::createGroupsPanel(void* data) +{ + return new LLPanelGroups(); +} + +// +// LLFloaterChatterBox +// +LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed) : + mActiveVoiceFloater(NULL) +{ + mAutoResize = FALSE; + + gUICtrlFactory->buildFloater(this, "floater_chatterbox.xml", NULL, FALSE); + addFloater(LLFloaterMyFriends::getInstance(0), TRUE); + if (gSavedSettings.getBOOL("ChatHistoryTornOff")) + { + LLFloaterChat* floater_chat = LLFloaterChat::getInstance(LLSD()); + // add then remove to set up relationship for re-attach + addFloater(floater_chat, FALSE); + removeFloater(floater_chat); + // reparent to floater view + gFloaterView->addChild(floater_chat); + } + else + { + addFloater(LLFloaterChat::getInstance(LLSD()), FALSE); + } + mTabContainer->lockTabs(); +} + +LLFloaterChatterBox::~LLFloaterChatterBox() +{ +} + +BOOL LLFloaterChatterBox::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) +{ + if (getEnabled() + && mask == MASK_CONTROL) + { + if (key == 'W') + { + LLFloater* floater = getActiveFloater(); + // is user closeable and is system closeable + if (floater && floater->canClose()) + { + if (floater->isCloseable()) + { + floater->close(); + } + else + { + // close chatterbox window if frontmost tab is reserved, non-closeable tab + // such as contacts or near me + close(); + } + } + return TRUE; + } + } + + return LLMultiFloater::handleKeyHere(key, mask, called_from_parent); +} + +void LLFloaterChatterBox::draw() +{ + // clear new im notifications when chatterbox is visible + if (!isMinimized()) + { + gIMMgr->clearNewIMNotification(); + } + LLFloater* current_active_floater = getCurrentVoiceFloater(); + // set icon on tab for floater currently associated with active voice channel + if(mActiveVoiceFloater != current_active_floater) + { + // remove image from old floater's tab + if (mActiveVoiceFloater) + { + mTabContainer->setTabImage(mActiveVoiceFloater, ""); + } + } + + // update image on current active tab + if (current_active_floater) + { + LLColor4 icon_color = LLColor4::white; + LLVoiceChannel* channelp = LLVoiceChannel::getCurrentVoiceChannel(); + if (channelp) + { + if (channelp->isActive()) + { + icon_color = LLColor4::green; + } + else if (channelp->getState() == LLVoiceChannel::STATE_ERROR) + { + icon_color = LLColor4::red; + } + else // active, but not connected + { + icon_color = LLColor4::yellow; + } + } + mTabContainer->setTabImage(current_active_floater, "active_voice_tab.tga", icon_color); + } + + mActiveVoiceFloater = current_active_floater; + + LLFloater::draw(); +} + +void LLFloaterChatterBox::onOpen() +{ + gSavedSettings.setBOOL("ShowCommunicate", TRUE); +} + +void LLFloaterChatterBox::onClose(bool app_quitting) +{ + setVisible(FALSE); + gSavedSettings.setBOOL("ShowCommunicate", FALSE); +} + +void LLFloaterChatterBox::removeFloater(LLFloater* floaterp) +{ + if (floaterp->getName() == "chat floater") + { + // only my friends floater now locked + mTabContainer->lockTabs(1); + gSavedSettings.setBOOL("ChatHistoryTornOff", TRUE); + floaterp->setCanClose(TRUE); + } + LLMultiFloater::removeFloater(floaterp); +} + +void LLFloaterChatterBox::addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainerCommon::eInsertionPoint insertion_point) +{ + // make sure my friends and chat history both locked when re-attaching chat history + if (floaterp->getName() == "chat floater") + { + // select my friends tab + mTabContainer->selectFirstTab(); + // add chat history to the right of the my friends tab + //*TODO: respect select_added_floater so that we don't leave first tab selected + LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::RIGHT_OF_CURRENT); + // make sure first two tabs are now locked + mTabContainer->lockTabs(2); + gSavedSettings.setBOOL("ChatHistoryTornOff", FALSE); + floaterp->setCanClose(FALSE); + } + else + { + LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + } + + // make sure active voice icon shows up for new tab + if (floaterp == mActiveVoiceFloater) + { + mTabContainer->setTabImage(floaterp, "active_voice_tab.tga"); + } +} + + +//static +LLFloaterChatterBox* LLFloaterChatterBox::showInstance(const LLSD& seed) +{ + LLFloaterChatterBox* floater = LLUISingleton::showInstance(seed); + + // if TRUE, show tab for active voice channel, otherwise, just show last tab + if (seed.asBoolean()) + { + LLFloater* floater_to_show = getCurrentVoiceFloater(); + if (floater_to_show) + { + floater_to_show->open(); + } + else + { + // just open chatterbox if there is no active voice window + LLUISingleton::getInstance(seed)->open(); + } + } + + return floater; +} + +//static +BOOL LLFloaterChatterBox::instanceVisible(const LLSD &seed) +{ + if (seed.asBoolean()) + { + LLFloater* floater_to_show = getCurrentVoiceFloater(); + if (floater_to_show) + { + return floater_to_show->isInVisibleChain(); + } + } + + return LLUISingleton::instanceVisible(seed); +} + +//static +LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater() +{ + if (!LLVoiceClient::voiceEnabled()) + { + return NULL; + } + if (LLVoiceChannelProximal::getInstance() == LLVoiceChannel::getCurrentVoiceChannel()) + { + // show near me tab if in proximal channel + return LLFloaterChat::getInstance(LLSD()); + } + else + { + LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance(LLSD()); + // iterator over all IM tabs (skip friends and near me) + for (S32 i = 0; i < floater->getFloaterCount(); i++) + { + LLPanel* panelp = floater->mTabContainer->getPanelByIndex(i); + if (panelp->getName() == "im_floater") + { + // only LLFloaterIMPanels are called "im_floater" + LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)panelp; + if (im_floaterp->getVoiceChannel() == LLVoiceChannel::getCurrentVoiceChannel()) + { + return im_floaterp; + } + } + } + } + return NULL; +} diff --git a/linden/indra/newview/llfloaterchatterbox.h b/linden/indra/newview/llfloaterchatterbox.h new file mode 100644 index 0000000..737f43e --- /dev/null +++ b/linden/indra/newview/llfloaterchatterbox.h @@ -0,0 +1,87 @@ +/** + * @file llfloaterchatterbox.h + * @author Richard + * @date 2007-05-04 + * @brief Integrated friends and group management/communication tool + * + * Copyright (c) 2007-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LL_LLFLOATERCHATTERBOX_H +#define LL_LLFLOATERCHATTERBOX_H + +#include "llfloater.h" +#include "llstring.h" + +class LLTabContainerCommon; + +class LLFloaterMyFriends : public LLFloater, public LLUISingleton +{ +public: + LLFloaterMyFriends(const LLSD& seed); + virtual ~LLFloaterMyFriends(); + + virtual BOOL postBuild(); + + void onClose(bool app_quitting); + + // override LLUISingleton behavior + static LLFloaterMyFriends* showInstance(const LLSD& id); + static void hideInstance(const LLSD& id); + static BOOL instanceVisible(const LLSD& id); + + static void* createFriendsPanel(void* data); + static void* createGroupsPanel(void* data); + +protected: + LLTabContainerCommon* mTabs; +}; + +class LLFloaterChatterBox : public LLMultiFloater, public LLUISingleton +{ +public: + LLFloaterChatterBox(const LLSD& seed); + virtual ~LLFloaterChatterBox(); + + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); + /*virtual*/ void draw(); + /*virtual*/ void onOpen(); + /*virtual*/ void onClose(bool app_quitting); + + /*virtual*/ void removeFloater(LLFloater* floaterp); + /*virtual*/ void addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainerCommon::eInsertionPoint insertion_point = LLTabContainerCommon::END); + + static LLFloaterChatterBox* showInstance(const LLSD& seed); + static BOOL instanceVisible(const LLSD& seed); + + static LLFloater* getCurrentVoiceFloater(); + +protected: + LLFloater* mActiveVoiceFloater; +}; + + +#endif // LL_LLFLOATERCHATTERBOX_H diff --git a/linden/indra/newview/llfloatercustomize.cpp b/linden/indra/newview/llfloatercustomize.cpp index 62ead8f..41bd8d7 100644 --- a/linden/indra/newview/llfloatercustomize.cpp +++ b/linden/indra/newview/llfloatercustomize.cpp @@ -489,7 +489,7 @@ void LLPanelEditWearable::addSubpart( const LLString& name, ESubpart id, LLSubpa { if (!name.empty()) { - childSetAction(name, &LLPanelEditWearable::onBtnSubpart, (void*)(S32)id); + childSetAction(name, &LLPanelEditWearable::onBtnSubpart, (void*)id); part->mButtonName = name; } mSubpartList[id] = part; @@ -1585,19 +1585,19 @@ BOOL LLFloaterCustomize::postBuild() initWearablePanels(); // Tab container - childSetTabChangeCallback("customize tab container", "Shape", onTabChanged, (void*)(S32)WT_SHAPE ); - childSetTabChangeCallback("customize tab container", "Skin", onTabChanged, (void*)(S32)WT_SKIN ); - childSetTabChangeCallback("customize tab container", "Hair", onTabChanged, (void*)(S32)WT_HAIR ); - childSetTabChangeCallback("customize tab container", "Eyes", onTabChanged, (void*)(S32)WT_EYES ); - childSetTabChangeCallback("customize tab container", "Shirt", onTabChanged, (void*)(S32)WT_SHIRT ); - childSetTabChangeCallback("customize tab container", "Pants", onTabChanged, (void*)(S32)WT_PANTS ); - childSetTabChangeCallback("customize tab container", "Shoes", onTabChanged, (void*)(S32)WT_SHOES ); - childSetTabChangeCallback("customize tab container", "Socks", onTabChanged, (void*)(S32)WT_SOCKS ); - childSetTabChangeCallback("customize tab container", "Jacket", onTabChanged, (void*)(S32)WT_JACKET ); - childSetTabChangeCallback("customize tab container", "Gloves", onTabChanged, (void*)(S32)WT_GLOVES ); - childSetTabChangeCallback("customize tab container", "Undershirt", onTabChanged, (void*)(S32)WT_UNDERSHIRT ); - childSetTabChangeCallback("customize tab container", "Underpants", onTabChanged, (void*)(S32)WT_UNDERPANTS ); - childSetTabChangeCallback("customize tab container", "Skirt", onTabChanged, (void*)(S32)WT_SKIRT ); + childSetTabChangeCallback("customize tab container", "Shape", onTabChanged, (void*)WT_SHAPE ); + childSetTabChangeCallback("customize tab container", "Skin", onTabChanged, (void*)WT_SKIN ); + childSetTabChangeCallback("customize tab container", "Hair", onTabChanged, (void*)WT_HAIR ); + childSetTabChangeCallback("customize tab container", "Eyes", onTabChanged, (void*)WT_EYES ); + childSetTabChangeCallback("customize tab container", "Shirt", onTabChanged, (void*)WT_SHIRT ); + childSetTabChangeCallback("customize tab container", "Pants", onTabChanged, (void*)WT_PANTS ); + childSetTabChangeCallback("customize tab container", "Shoes", onTabChanged, (void*)WT_SHOES ); + childSetTabChangeCallback("customize tab container", "Socks", onTabChanged, (void*)WT_SOCKS ); + childSetTabChangeCallback("customize tab container", "Jacket", onTabChanged, (void*)WT_JACKET ); + childSetTabChangeCallback("customize tab container", "Gloves", onTabChanged, (void*)WT_GLOVES ); + childSetTabChangeCallback("customize tab container", "Undershirt", onTabChanged, (void*)WT_UNDERSHIRT ); + childSetTabChangeCallback("customize tab container", "Underpants", onTabChanged, (void*)WT_UNDERPANTS ); + childSetTabChangeCallback("customize tab container", "Skirt", onTabChanged, (void*)WT_SKIRT ); // Remove underware panels for teens if (gAgent.mAccess < SIM_ACCESS_MATURE) diff --git a/linden/indra/newview/llfloaterdirectory.cpp b/linden/indra/newview/llfloaterdirectory.cpp index aea55f7..3a05715 100644 --- a/linden/indra/newview/llfloaterdirectory.cpp +++ b/linden/indra/newview/llfloaterdirectory.cpp @@ -347,13 +347,13 @@ void LLFloaterDirectory::refreshGroup(const LLUUID& group_id) LLFloaterDirectory::~LLFloaterDirectory() { sInstance = NULL; - delete mPanelAvatarp; - delete mPanelEventp; - delete mPanelGroupp; - delete mPanelGroupHolderp; - delete mPanelPlacep; - delete mPanelPlaceSmallp; - delete mPanelClassifiedp; + delete mPanelAvatarp; mPanelAvatarp = NULL; + delete mPanelEventp; mPanelEventp = NULL; + delete mPanelGroupp; mPanelGroupp = NULL; + delete mPanelGroupHolderp; mPanelGroupHolderp = NULL; + delete mPanelPlacep; mPanelPlacep = NULL; + delete mPanelPlaceSmallp; mPanelPlaceSmallp = NULL; + delete mPanelClassifiedp; mPanelClassifiedp = NULL; gSavedSettings.setBOOL("ShowDirectory", FALSE); } diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp index d01a24b..78447e9 100644 --- a/linden/indra/newview/llfloaterfriends.cpp +++ b/linden/indra/newview/llfloaterfriends.cpp @@ -63,20 +63,18 @@ class LLLocalFriendsObserver : public LLFriendObserver { public: - LLLocalFriendsObserver(LLFloaterFriends* floater) : mFloater(floater) {} + LLLocalFriendsObserver(LLPanelFriends* floater) : mFloater(floater) {} virtual ~LLLocalFriendsObserver() { mFloater = NULL; } virtual void changed(U32 mask) { mFloater->updateFriends(mask); } protected: - LLFloaterFriends* mFloater; + LLPanelFriends* mFloater; }; -LLFloaterFriends* LLFloaterFriends::sInstance = NULL; - -LLFloaterFriends::LLFloaterFriends() : - LLFloater("Friends"), +LLPanelFriends::LLPanelFriends() : + LLPanel(), LLEventTimer(1000000), mObserver(NULL), mMenuState(0), @@ -84,80 +82,38 @@ LLFloaterFriends::LLFloaterFriends() : mAllowRightsChange(TRUE), mNumRightsChanged(0) { - mTimer.stop(); - sInstance = this; + mEventTimer.stop(); mObserver = new LLLocalFriendsObserver(this); LLAvatarTracker::instance().addObserver(mObserver); - gSavedSettings.setBOOL("ShowFriends", TRUE); - // Builds and adds to gFloaterView - gUICtrlFactory->buildFloater(this, "floater_friends.xml"); } -LLFloaterFriends::~LLFloaterFriends() +LLPanelFriends::~LLPanelFriends() { LLAvatarTracker::instance().removeObserver(mObserver); delete mObserver; - sInstance = NULL; - gSavedSettings.setBOOL("ShowFriends", FALSE); } -void LLFloaterFriends::tick() +void LLPanelFriends::tick() { - mTimer.stop(); + mEventTimer.stop(); mPeriod = 1000000; mAllowRightsChange = TRUE; updateFriends(LLFriendObserver::ADD); } -// static -void LLFloaterFriends::show(void*) -{ - if(sInstance) - { - sInstance->open(); /*Flawfinder: ignore*/ - } - else - { - LLFloaterFriends* self = new LLFloaterFriends; - self->open(); /*Flawfinder: ignore*/ - } -} - - -// static -BOOL LLFloaterFriends::visible(void*) -{ - return sInstance && sInstance->getVisible(); -} - - -// static -void LLFloaterFriends::toggle(void*) -{ - if (sInstance) - { - sInstance->close(); - } - else - { - show(); - } -} - - -void LLFloaterFriends::updateFriends(U32 changed_mask) +void LLPanelFriends::updateFriends(U32 changed_mask) { LLUUID selected_id; - LLCtrlListInterface *friends_list = sInstance->childGetListInterface("friend_list"); + LLCtrlListInterface *friends_list = childGetListInterface("friend_list"); if (!friends_list) return; - LLCtrlScrollInterface *friends_scroll = sInstance->childGetScrollInterface("friend_list"); + LLCtrlScrollInterface *friends_scroll = childGetScrollInterface("friend_list"); if (!friends_scroll) return; // We kill the selection warning, otherwise we'll spam with warning popups // if the maximum amount of friends are selected mShowMaxSelectWarning = false; - LLDynamicArray selected_friends = sInstance->getSelectedIDs(); + LLDynamicArray selected_friends = getSelectedIDs(); if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) { refreshNames(); @@ -168,8 +124,8 @@ void LLFloaterFriends::updateFriends(U32 changed_mask) if(mNumRightsChanged > 0) { mPeriod = RIGHTS_CHANGE_TIMEOUT; - mTimer.start(); - mTimer.reset(); + mEventTimer.start(); + mEventTimer.reset(); mAllowRightsChange = FALSE; } else @@ -194,12 +150,12 @@ void LLFloaterFriends::updateFriends(U32 changed_mask) } // virtual -BOOL LLFloaterFriends::postBuild() +BOOL LLPanelFriends::postBuild() { - mFriendsList = LLUICtrlFactory::getScrollListByName(this, "friend_list"); mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT); mFriendsList->setMaxiumumSelectCallback(onMaximumSelect); + mFriendsList->setCommitOnSelectionChange(TRUE); childSetCommitCallback("friend_list", onSelectName, this); childSetDoubleClickCallback("friend_list", onClickIM); @@ -214,14 +170,17 @@ BOOL LLFloaterFriends::postBuild() childSetAction("pay_btn", onClickPay, this); childSetAction("add_btn", onClickAddFriend, this); childSetAction("remove_btn", onClickRemove, this); - childSetAction("close_btn", onClickClose, this); + setDefaultBtn("im_btn"); + + updateFriends(LLFriendObserver::ADD); refreshUI(); + return TRUE; } -void LLFloaterFriends::addFriend(const std::string& name, const LLUUID& agent_id) +void LLPanelFriends::addFriend(const std::string& name, const LLUUID& agent_id) { LLAvatarTracker& at = LLAvatarTracker::instance(); const LLRelationship* relationInfo = at.getBuddyInfo(agent_id); @@ -275,17 +234,26 @@ void LLFloaterFriends::addFriend(const std::string& name, const LLUUID& agent_id mFriendsList->addElement(element, ADD_BOTTOM); } -void LLFloaterFriends::refreshRightsChangeList(U8 state) +void LLPanelFriends::refreshRightsChangeList() { LLDynamicArray friends = getSelectedIDs(); - const LLRelationship* friend_status = NULL; - if(friends.size() > 0) friend_status = LLAvatarTracker::instance().getBuddyInfo(friends[0]); + S32 num_selected = friends.size(); LLSD row; - bool can_change_visibility = false; - bool can_change_modify = false; - bool can_change_online_multiple = true; - bool can_change_map_multiple = true; + bool can_offer_teleport = num_selected >= 1; + + // aggregate permissions over all selected friends + bool friends_see_online = true; + bool friends_see_on_map = true; + bool friends_modify_objects = true; + + // do at least some of the friends selected have these rights? + bool some_friends_see_online = false; + bool some_friends_see_on_map = false; + bool some_friends_modify_objects = false; + + bool selected_friends_online = true; + LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label"); if(!mAllowRightsChange) @@ -293,7 +261,9 @@ void LLFloaterFriends::refreshRightsChangeList(U8 state) if(processing_label) { processing_label->setVisible(true); - state = 0; + // ignore selection for now + friends.clear(); + num_selected = 0; } } else @@ -304,82 +274,111 @@ void LLFloaterFriends::refreshRightsChangeList(U8 state) } } - if(state == 1) - { - if(friend_status && !friend_status->isOnline()) - { - childSetEnabled("offer_teleport_btn", false); - } - can_change_visibility = true; - can_change_modify = true; - } - else if (state == 2) + const LLRelationship* friend_status = NULL; + for(LLDynamicArray::iterator itr = friends.begin(); itr != friends.end(); ++itr) { - can_change_visibility = true; - can_change_modify = false; - for(LLDynamicArray::iterator itr = friends.begin(); itr != friends.end(); ++itr) + friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr); + if (friend_status) { - friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr); + bool can_see_online = friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS); + bool can_see_on_map = friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION); + bool can_modify_objects = friend_status->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS); + + // aggregate rights of this friend into total selection + friends_see_online &= can_see_online; + friends_see_on_map &= can_see_on_map; + friends_modify_objects &= can_modify_objects; + + // can at least one of your selected friends do any of these? + some_friends_see_online |= can_see_online; + some_friends_see_on_map |= can_see_on_map; + some_friends_modify_objects |= can_modify_objects; + if(!friend_status->isOnline()) { - childSetEnabled("offer_teleport_btn", false); - } - if(!friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS)) - { - can_change_online_multiple = false; - can_change_map_multiple = false; - } - else if(!friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION)) - { - can_change_map_multiple = false; + can_offer_teleport = false; + selected_friends_online = false; } } - + else // missing buddy info, don't allow any operations + { + can_offer_teleport = false; + + friends_see_online = false; + friends_see_on_map = false; + friends_modify_objects = false; + + some_friends_see_online = false; + some_friends_see_on_map = false; + some_friends_modify_objects = false; + } } - LLCheckboxCtrl* check; + // seeing a friend on the map requires seeing online status as a prerequisite + friends_see_on_map &= friends_see_online; + mMenuState = 0; - check = LLUICtrlFactory::getCheckBoxByName(this, "online_status_cb"); - check->setEnabled(can_change_visibility); - check->set(FALSE); - if(!mAllowRightsChange) check->setVisible(FALSE); - else check->setVisible(TRUE); - if(friend_status) + // make checkboxes visible after we have finished processing rights + childSetVisible("online_status_cb", mAllowRightsChange); + childSetVisible("map_status_cb", mAllowRightsChange); + childSetVisible("modify_status_cb", mAllowRightsChange); + + if (num_selected == 0) // nothing selected { - check->set(friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS) && can_change_online_multiple); - if(friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS)) mMenuState |= LLRelationship::GRANT_ONLINE_STATUS; + childSetEnabled("im_btn", FALSE); + childSetEnabled("offer_teleport_btn", FALSE); + + childSetEnabled("online_status_cb", FALSE); + childSetValue("online_status_cb", FALSE); + childSetTentative("online_status_cb", FALSE); + + childSetEnabled("map_status_cb", FALSE); + childSetValue("map_status_cb", FALSE); + childSetTentative("map_status_cb", FALSE); + + childSetEnabled("modify_status_cb", FALSE); + childSetValue("modify_status_cb", FALSE); + childSetTentative("modify_status_cb", FALSE); } - - check = LLUICtrlFactory::getCheckBoxByName(this, "map_status_cb"); - check->setEnabled(false); - check->set(FALSE); - if(!mAllowRightsChange) check->setVisible(FALSE); - else check->setVisible(TRUE); - if(friend_status) + else // we have at least one friend selected... { - check->setEnabled(friend_status->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS) && can_change_visibility && can_change_online_multiple); - check->set(friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION) && can_change_map_multiple); - if(friend_status->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION)) mMenuState |= LLRelationship::GRANT_MAP_LOCATION; - } + // only allow IMs to groups when everyone in the group is online + // to be consistent with context menus in inventory and because otherwise + // offline friends would be silently dropped from the session + childSetEnabled("im_btn", selected_friends_online || num_selected == 1); - check = LLUICtrlFactory::getCheckBoxByName(this, "modify_status_cb"); - check->setEnabled(can_change_modify); - check->set(FALSE); - if(!mAllowRightsChange) check->setVisible(FALSE); - else check->setVisible(TRUE); - if(can_change_modify) - { - if(friend_status) + childSetEnabled("offer_teleport_btn", can_offer_teleport); + + childSetEnabled("online_status_cb", TRUE); + childSetValue("online_status_cb", some_friends_see_online); + childSetTentative("online_status_cb", some_friends_see_online != friends_see_online); + if (friends_see_online) + { + mMenuState |= LLRelationship::GRANT_ONLINE_STATUS; + } + + childSetEnabled("map_status_cb", TRUE); + childSetValue("map_status_cb", some_friends_see_on_map); + childSetTentative("map_status_cb", some_friends_see_on_map != friends_see_on_map); + if(friends_see_on_map) { - check->set(friend_status->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS)); - if(friend_status->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS)) mMenuState |= LLRelationship::GRANT_MODIFY_OBJECTS; + mMenuState |= LLRelationship::GRANT_MAP_LOCATION; + } + + // for now, don't allow modify rights change for multiple select + childSetEnabled("modify_status_cb", num_selected == 1); + childSetValue("modify_status_cb", some_friends_modify_objects); + childSetTentative("modify_status_cb", some_friends_modify_objects != friends_modify_objects); + if(friends_modify_objects) + { + mMenuState |= LLRelationship::GRANT_MODIFY_OBJECTS; } } } -void LLFloaterFriends::refreshNames() +void LLPanelFriends::refreshNames() { LLDynamicArray selected_ids = getSelectedIDs(); S32 pos = mFriendsList->getScrollPos(); @@ -409,7 +408,7 @@ void LLFloaterFriends::refreshNames() } -void LLFloaterFriends::refreshUI() +void LLPanelFriends::refreshUI() { BOOL single_selected = FALSE; BOOL multiple_selected = FALSE; @@ -443,40 +442,34 @@ void LLFloaterFriends::refreshUI() childSetEnabled("im_btn", single_selected); childSetEnabled("friend_rights", single_selected); - //Note: We reset this in refreshRightsChangeList since we already have to iterate - //through all selected friends there - childSetEnabled("offer_teleport_btn", single_selected); - - refreshRightsChangeList((single_selected + multiple_selected)); + refreshRightsChangeList(); } -// static -LLDynamicArray LLFloaterFriends::getSelectedIDs() +LLDynamicArray LLPanelFriends::getSelectedIDs() { LLUUID selected_id; LLDynamicArray friend_ids; - if(sInstance) + std::vector selected = mFriendsList->getAllSelected(); + for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) { - std::vector selected = sInstance->mFriendsList->getAllSelected(); - for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) - { - friend_ids.push_back((*itr)->getUUID()); - } + friend_ids.push_back((*itr)->getUUID()); } return friend_ids; } // static -void LLFloaterFriends::onSelectName(LLUICtrl* ctrl, void* user_data) +void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data) { - if(sInstance) + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + if(panelp) { - sInstance->refreshUI(); + panelp->refreshUI(); } } //static -void LLFloaterFriends::onMaximumSelect(void* user_data) +void LLPanelFriends::onMaximumSelect(void* user_data) { LLString::format_map_t args; args["[MAX_SELECT]"] = llformat("%d", MAX_FRIEND_SELECT); @@ -484,10 +477,12 @@ void LLFloaterFriends::onMaximumSelect(void* user_data) }; // static -void LLFloaterFriends::onClickProfile(void* user_data) +void LLPanelFriends::onClickProfile(void* user_data) { - //llinfos << "LLFloaterFriends::onClickProfile()" << llendl; - LLDynamicArray ids = getSelectedIDs(); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + //llinfos << "LLPanelFriends::onClickProfile()" << llendl; + LLDynamicArray ids = panelp->getSelectedIDs(); if(ids.size() > 0) { LLUUID agent_id = ids[0]; @@ -498,10 +493,12 @@ void LLFloaterFriends::onClickProfile(void* user_data) } // static -void LLFloaterFriends::onClickIM(void* user_data) +void LLPanelFriends::onClickIM(void* user_data) { - //llinfos << "LLFloaterFriends::onClickIM()" << llendl; - LLDynamicArray ids = getSelectedIDs(); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + //llinfos << "LLPanelFriends::onClickIM()" << llendl; + LLDynamicArray ids = panelp->getSelectedIDs(); if(ids.size() > 0) { if(ids.size() == 1) @@ -514,8 +511,8 @@ void LLFloaterFriends::onClickIM(void* user_data) { char buffer[MAX_STRING]; /* Flawfinder: ignore */ snprintf(buffer, MAX_STRING, "%s %s", first, last); /* Flawfinder: ignore */ - gIMView->setFloaterOpen(TRUE); - gIMView->addSession( + gIMMgr->setFloaterOpen(TRUE); + gIMMgr->addSession( buffer, IM_NOTHING_SPECIAL, agent_id); @@ -523,17 +520,18 @@ void LLFloaterFriends::onClickIM(void* user_data) } else { - gIMView->setFloaterOpen(TRUE); - gIMView->addSession("Friends Conference", + gIMMgr->setFloaterOpen(TRUE); + gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], ids); } + make_ui_sound("UISndStartIM"); } } // static -void LLFloaterFriends::requestFriendship(const LLUUID& target_id, const LLString& target_name) +void LLPanelFriends::requestFriendship(const LLUUID& target_id, const LLString& target_name) { // HACK: folder id stored as "message" LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); @@ -552,7 +550,7 @@ struct LLAddFriendData }; // static -void LLFloaterFriends::callbackAddFriend(S32 option, void* data) +void LLPanelFriends::callbackAddFriend(S32 option, void* data) { LLAddFriendData* add = (LLAddFriendData*)data; if (option == 0) @@ -563,7 +561,7 @@ void LLFloaterFriends::callbackAddFriend(S32 option, void* data) } // static -void LLFloaterFriends::onPickAvatar(const std::vector& names, +void LLPanelFriends::onPickAvatar(const std::vector& names, const std::vector& ids, void* ) { @@ -573,7 +571,7 @@ void LLFloaterFriends::onPickAvatar(const std::vector& names, } // static -void LLFloaterFriends::requestFriendshipDialog(const LLUUID& id, +void LLPanelFriends::requestFriendshipDialog(const LLUUID& id, const std::string& name) { if(id == gAgentID) @@ -593,16 +591,24 @@ void LLFloaterFriends::requestFriendshipDialog(const LLUUID& id, } // static -void LLFloaterFriends::onClickAddFriend(void* user_data) +void LLPanelFriends::onClickAddFriend(void* user_data) { - LLFloaterAvatarPicker::show(onPickAvatar, user_data, FALSE, TRUE); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + LLFloater* root_floater = gFloaterView->getParentFloater(panelp); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onPickAvatar, user_data, FALSE, TRUE); + if (root_floater) + { + root_floater->addDependentFloater(picker); + } } // static -void LLFloaterFriends::onClickRemove(void* user_data) +void LLPanelFriends::onClickRemove(void* user_data) { - //llinfos << "LLFloaterFriends::onClickRemove()" << llendl; - LLDynamicArray ids = getSelectedIDs(); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + //llinfos << "LLPanelFriends::onClickRemove()" << llendl; + LLDynamicArray ids = panelp->getSelectedIDs(); LLStringBase::format_map_t args; if(ids.size() > 0) { @@ -630,9 +636,11 @@ void LLFloaterFriends::onClickRemove(void* user_data) } // static -void LLFloaterFriends::onClickOfferTeleport(void*) +void LLPanelFriends::onClickOfferTeleport(void* user_data) { - LLDynamicArray ids = getSelectedIDs(); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + LLDynamicArray ids = panelp->getSelectedIDs(); if(ids.size() > 0) { handle_lure(ids); @@ -640,43 +648,40 @@ void LLFloaterFriends::onClickOfferTeleport(void*) } // static -void LLFloaterFriends::onClickPay(void*) +void LLPanelFriends::onClickPay(void* user_data) { - LLDynamicArray ids = getSelectedIDs(); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + LLDynamicArray ids = panelp->getSelectedIDs(); if(ids.size() == 1) { handle_pay_by_id(ids[0]); } } -// static -void LLFloaterFriends::onClickClose(void* user_data) +void LLPanelFriends::onClickOnlineStatus(LLUICtrl* ctrl, void* user_data) { - //llinfos << "LLFloaterFriends::onClickClose()" << llendl; - if(sInstance) - { - sInstance->onClose(false); - } -} + LLPanelFriends* panelp = (LLPanelFriends*)user_data; -void LLFloaterFriends::onClickOnlineStatus(LLUICtrl* ctrl, void* user_data) -{ bool checked = ctrl->getValue(); - sInstance->updateMenuState(LLRelationship::GRANT_ONLINE_STATUS, checked); - sInstance->applyRightsToFriends(LLRelationship::GRANT_ONLINE_STATUS, checked); + panelp->updateMenuState(LLRelationship::GRANT_ONLINE_STATUS, checked); + panelp->applyRightsToFriends(LLRelationship::GRANT_ONLINE_STATUS, checked); } -void LLFloaterFriends::onClickMapStatus(LLUICtrl* ctrl, void* user_data) +void LLPanelFriends::onClickMapStatus(LLUICtrl* ctrl, void* user_data) { + LLPanelFriends* panelp = (LLPanelFriends*)user_data; bool checked = ctrl->getValue(); - sInstance->updateMenuState(LLRelationship::GRANT_MAP_LOCATION, checked); - sInstance->applyRightsToFriends(LLRelationship::GRANT_MAP_LOCATION, checked); + panelp->updateMenuState(LLRelationship::GRANT_MAP_LOCATION, checked); + panelp->applyRightsToFriends(LLRelationship::GRANT_MAP_LOCATION, checked); } -void LLFloaterFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data) +void LLPanelFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data) { + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + bool checked = ctrl->getValue(); - LLDynamicArray ids = getSelectedIDs(); + LLDynamicArray ids = panelp->getSelectedIDs(); LLStringBase::format_map_t args; if(ids.size() > 0) { @@ -690,33 +695,35 @@ void LLFloaterFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data) args["[FIRST_NAME]"] = first; args["[LAST_NAME]"] = last; } - if(checked) gViewerWindow->alertXml("GrantModifyRights", args, handleModifyRights, NULL); - else gViewerWindow->alertXml("RevokeModifyRights", args, handleModifyRights, NULL); + if(checked) gViewerWindow->alertXml("GrantModifyRights", args, handleModifyRights, user_data); + else gViewerWindow->alertXml("RevokeModifyRights", args, handleModifyRights, user_data); } else return; } } -void LLFloaterFriends::handleModifyRights(S32 option, void* user_data) +void LLPanelFriends::handleModifyRights(S32 option, void* user_data) { - if(sInstance) + LLPanelFriends* panelp = (LLPanelFriends*)user_data; + + if(panelp) { if(!option) { - sInstance->updateMenuState(LLRelationship::GRANT_MODIFY_OBJECTS, !((sInstance->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); - sInstance->applyRightsToFriends(LLRelationship::GRANT_MODIFY_OBJECTS, ((sInstance->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); + panelp->updateMenuState(LLRelationship::GRANT_MODIFY_OBJECTS, !((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); + panelp->applyRightsToFriends(LLRelationship::GRANT_MODIFY_OBJECTS, ((panelp->getMenuState() & LLRelationship::GRANT_MODIFY_OBJECTS) != 0)); } - sInstance->refreshUI(); + panelp->refreshUI(); } } -void LLFloaterFriends::updateMenuState(S32 flag, BOOL value) +void LLPanelFriends::updateMenuState(S32 flag, BOOL value) { if(value) mMenuState |= flag; else mMenuState &= ~flag; } -void LLFloaterFriends::applyRightsToFriends(S32 flag, BOOL value) +void LLPanelFriends::applyRightsToFriends(S32 flag, BOOL value) { LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_GrantUserRights); @@ -745,7 +752,7 @@ void LLFloaterFriends::applyRightsToFriends(S32 flag, BOOL value) // static -void LLFloaterFriends::handleRemove(S32 option, void* user_data) +void LLPanelFriends::handleRemove(S32 option, void* user_data) { LLDynamicArray* ids = static_cast*>(user_data); for(LLDynamicArray::iterator itr = ids->begin(); itr != ids->end(); ++itr) diff --git a/linden/indra/newview/llfloaterfriends.h b/linden/indra/newview/llfloaterfriends.h index 327a8cf..0b6646d 100644 --- a/linden/indra/newview/llfloaterfriends.h +++ b/linden/indra/newview/llfloaterfriends.h @@ -31,7 +31,7 @@ #ifndef LL_LLFLOATERFRIENDS_H #define LL_LLFLOATERFRIENDS_H -#include "llfloater.h" +#include "llpanel.h" #include "llstring.h" #include "lluuid.h" #include "lltimer.h" @@ -40,24 +40,23 @@ class LLFriendObserver; /** - * @class LLFloaterFriends + * @class LLPanelFriends * @brief An instance of this class is used for displaying your friends * and gives you quick access to all agents which a user relationship. * * @sa LLFloater */ -class LLFloaterFriends : public LLFloater, public LLEventTimer +class LLPanelFriends : public LLPanel, public LLEventTimer { public: - virtual ~LLFloaterFriends(); + LLPanelFriends(); + virtual ~LLPanelFriends(); /** * @brief This method either creates or brings to the front the * current instantiation of this floater. There is only once since * you can currently only look at your local friends. */ - static void show(void* ignored = NULL); - virtual void tick(); /** @@ -68,11 +67,6 @@ public: virtual BOOL postBuild(); - static BOOL visible(void* unused = NULL); - - // Toggles visibility of floater - static void toggle(void* unused = NULL); - // Show a dialog explaining what friendship entails, then request // friendship. JC static void requestFriendshipDialog(const LLUUID& target_id, @@ -95,19 +89,18 @@ private: }; // protected members - LLFloaterFriends(); void reloadNames(); void refreshNames(); void refreshUI(); - void refreshRightsChangeList(U8 state); + void refreshRightsChangeList(); void applyRightsToFriends(S32 flag, BOOL value); void updateMenuState(S32 flag, BOOL value); S32 getMenuState() { return mMenuState; } void addFriend(const std::string& name, const LLUUID& agent_id); // return LLUUID::null if nothing is selected - static LLDynamicArray getSelectedIDs(); + LLDynamicArray getSelectedIDs(); // callback methods static void onSelectName(LLUICtrl* ctrl, void* user_data); @@ -123,8 +116,6 @@ private: static void onClickOfferTeleport(void* user_data); static void onClickPay(void* user_data); - static void onClickClose(void* user_data); - static void onClickOnlineStatus(LLUICtrl* ctrl, void* user_data); static void onClickMapStatus(LLUICtrl* ctrl, void* user_data); static void onClickModifyStatus(LLUICtrl* ctrl, void* user_data); @@ -133,9 +124,6 @@ private: static void handleModifyRights(S32 option, void* user_data); private: - // static data - static LLFloaterFriends* sInstance; - // member data LLFriendObserver* mObserver; LLUUID mAddFriendID; diff --git a/linden/indra/newview/llfloatergroups.cpp b/linden/indra/newview/llfloatergroups.cpp index 53d5147..74526e1 100644 --- a/linden/indra/newview/llfloatergroups.cpp +++ b/linden/indra/newview/llfloatergroups.cpp @@ -1,6 +1,6 @@ /** * @file llfloatergroups.cpp - * @brief LLFloaterGroups class implementation + * @brief LLPanelGroups class implementation * * Copyright (c) 2002-2007, Linden Research, Inc. * @@ -50,115 +50,135 @@ #include "lltextbox.h" #include "llvieweruictrlfactory.h" #include "llviewerwindow.h" - -const LLRect FLOATER_RECT(0, 258, 280, 0); -const char FLOATER_TITLE[] = "Groups"; +#include "llimview.h" // static -LLMap LLFloaterGroups::sInstances; +std::map LLFloaterGroupPicker::sInstances; +// helper functions +void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id); ///---------------------------------------------------------------------------- -/// Class LLFloaterGroups +/// Class LLFloaterGroupPicker ///---------------------------------------------------------------------------- -//LLEventListener -//virtual -bool LLFloaterGroups::handleEvent(LLPointer event, const LLSD& userdata) +// static +LLFloaterGroupPicker* LLFloaterGroupPicker::findInstance(const LLSD& seed) { - if (event->desc() == "new group") + instance_map_t::iterator found_it = sInstances.find(seed.asUUID()); + if (found_it != sInstances.end()) { - reset(); - return true; + return found_it->second; } - - return LLView::handleEvent(event, userdata); + return NULL; } -// Call this with an agent id and AGENT_GROUPS for an agent's -// groups, otherwise, call with an object id and SET_OBJECT_GROUP -// when modifying an object. // static -LLFloaterGroups* LLFloaterGroups::show(const LLUUID& id, EGroupDialog type) +LLFloaterGroupPicker* LLFloaterGroupPicker::createInstance(const LLSD &seed) +{ + LLFloaterGroupPicker* pickerp = new LLFloaterGroupPicker(seed); + gUICtrlFactory->buildFloater(pickerp, "floater_choose_group.xml"); + return pickerp; +} + +LLFloaterGroupPicker::LLFloaterGroupPicker(const LLSD& seed) : + mSelectCallback(NULL), + mCallbackUserdata(NULL) +{ + mID = seed.asUUID(); + sInstances.insert(std::make_pair(mID, this)); +} + +LLFloaterGroupPicker::~LLFloaterGroupPicker() +{ + sInstances.erase(mID); +} + +void LLFloaterGroupPicker::setSelectCallback(void (*callback)(LLUUID, void*), + void* userdata) { - LLFloaterGroups* instance = NULL; - if(sInstances.checkData(id)) + mSelectCallback = callback; + mCallbackUserdata = userdata; +} + +BOOL LLFloaterGroupPicker::postBuild() +{ + init_group_list(LLUICtrlFactory::getScrollListByName(this, "group list"), gAgent.getGroupID()); + + childSetAction("OK", onBtnOK, this); + + childSetAction("Cancel", onBtnCancel, this); + + setDefaultBtn("OK"); + + childSetDoubleClickCallback("group list", onBtnOK); + childSetUserData("group list", this); + + childEnable("OK"); + + return TRUE; +} + +void LLFloaterGroupPicker::onBtnOK(void* userdata) +{ + LLFloaterGroupPicker* self = (LLFloaterGroupPicker*)userdata; + if(self) self->ok(); +} + +void LLFloaterGroupPicker::onBtnCancel(void* userdata) +{ + LLFloaterGroupPicker* self = (LLFloaterGroupPicker*)userdata; + if(self) self->close(); +} + + +void LLFloaterGroupPicker::ok() +{ + LLCtrlListInterface *group_list = childGetListInterface("group list"); + LLUUID group_id; + if (group_list) { - instance = sInstances.getData(id); - if (instance->getType() != type) - { - // not the type we want ==> destroy it and rebuild below - instance->destroy(); - instance = NULL; - } - else - { - // Move the existing view to the front - instance->open(); /* Flawfinder: ignore */ - } + group_id = group_list->getCurrentID(); } - - if (!instance) + if(mSelectCallback) { - S32 left = 0; - S32 top = 0; - LLRect rect = FLOATER_RECT; - rect.translate( left - rect.mLeft, top - rect.mTop ); - instance = new LLFloaterGroups("groups", rect, FLOATER_TITLE, id); - if(instance) - { - sInstances.addData(id, instance); - //instance->init(type); - instance->mType = type; - switch (type) - { - case AGENT_GROUPS: - gUICtrlFactory->buildFloater(instance, "floater_groups.xml"); - break; - case CHOOSE_ONE: - gUICtrlFactory->buildFloater(instance, "floater_choose_group.xml"); - break; - } - instance->center(); - instance->open(); /*Flawfinder: ignore*/ - } + mSelectCallback(group_id, mCallbackUserdata); } - return instance; + + close(); } -// static -LLFloaterGroups* LLFloaterGroups::getInstance(const LLUUID& id) +///---------------------------------------------------------------------------- +/// Class LLPanelGroups +///---------------------------------------------------------------------------- + +//LLEventListener +//virtual +bool LLPanelGroups::handleEvent(LLPointer event, const LLSD& userdata) { - if(sInstances.checkData(id)) + if (event->desc() == "new group") { - return sInstances.getData(id); + reset(); + return true; } - return NULL; + + return LLView::handleEvent(event, userdata); } // Default constructor -LLFloaterGroups::LLFloaterGroups(const std::string& name, - const LLRect& rect, - const std::string& title, - const LLUUID& id) : - LLFloater(name, rect, title), - mID(id), - mType(AGENT_GROUPS), - mOKCallback(NULL), - mCallbackUserdata(NULL) +LLPanelGroups::LLPanelGroups() : + LLPanel() { + gAgent.addListener(this, "new group"); } -// Destroys the object -LLFloaterGroups::~LLFloaterGroups() +LLPanelGroups::~LLPanelGroups() { - gFocusMgr.releaseFocusIfNeeded( this ); - - sInstances.removeData(mID); + gAgent.removeListener(this); } // clear the group list, and get a fresh set of info. -void LLFloaterGroups::reset() +void LLPanelGroups::reset() { LLCtrlListInterface *group_list = childGetListInterface("group list"); if (group_list) @@ -168,215 +188,126 @@ void LLFloaterGroups::reset() childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); - initAgentGroups(gAgent.getGroupID()); + init_group_list(LLUICtrlFactory::getScrollListByName(this, "group list"), gAgent.getGroupID()); enableButtons(); } -void LLFloaterGroups::setOkCallback(void (*callback)(LLUUID, void*), - void* userdata) -{ - mOKCallback = callback; - mCallbackUserdata = userdata; -} - -BOOL LLFloaterGroups::postBuild() +BOOL LLPanelGroups::postBuild() { childSetCommitCallback("group list", onGroupList, this); - if(mType == AGENT_GROUPS) - { - childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); - childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); - - initAgentGroups(gAgent.getGroupID()); - - childSetAction("Activate", onBtnActivate, this); + childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); + childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS)); - childSetAction("Info", onBtnInfo, this); + init_group_list(LLUICtrlFactory::getScrollListByName(this, "group list"), gAgent.getGroupID()); - childSetAction("Leave", onBtnLeave, this); + childSetAction("Activate", onBtnActivate, this); - childSetAction("Create", onBtnCreate, this); + childSetAction("Info", onBtnInfo, this); - childSetAction("Search...", onBtnSearch, this); + childSetAction("IM", onBtnIM, this); - childSetAction("Close", onBtnCancel, this); + childSetAction("Leave", onBtnLeave, this); - setDefaultBtn("Info"); + childSetAction("Create", onBtnCreate, this); - childSetDoubleClickCallback("group list", onBtnInfo); - childSetUserData("group list", this); - } - else - { - initAgentGroups(gAgent.getGroupID()); - - childSetAction("OK", onBtnOK, this); + childSetAction("Search...", onBtnSearch, this); - childSetAction("Cancel", onBtnCancel, this); + setDefaultBtn("IM"); - setDefaultBtn("OK"); + childSetDoubleClickCallback("group list", onBtnIM); + childSetUserData("group list", this); - childSetDoubleClickCallback("group list", onBtnOK); - childSetUserData("group list", this); - } - - enableButtons(); + reset(); return TRUE; } -void LLFloaterGroups::initAgentGroups(const LLUUID& highlight_id) +void LLPanelGroups::enableButtons() { - S32 count = gAgent.mGroups.count(); - LLUUID id; LLCtrlListInterface *group_list = childGetListInterface("group list"); - if (!group_list) return; - - group_list->operateOnAll(LLCtrlListInterface::OP_DELETE); - - for(S32 i = 0; i < count; ++i) + LLUUID group_id; + if (group_list) { - id = gAgent.mGroups.get(i).mID; - LLGroupData* group_datap = &gAgent.mGroups.get(i); - LLString style = "NORMAL"; - if(highlight_id == id) - { - style = "BOLD"; - } - - LLSD element; - element["id"] = id; - element["columns"][0]["column"] = "name"; - element["columns"][0]["value"] = group_datap->mName; - element["columns"][0]["font"] = "SANSSERIF"; - element["columns"][0]["font-style"] = style; - - group_list->addElement(element, ADD_SORTED); + group_id = group_list->getCurrentID(); } + if(group_id != gAgent.getGroupID()) { - LLString style = "NORMAL"; - if (highlight_id.isNull()) - { - style = "BOLD"; - } - LLSD element; - element["id"] = LLUUID::null; - element["columns"][0]["column"] = "name"; - element["columns"][0]["value"] = "none"; - element["columns"][0]["font"] = "SANSSERIF"; - element["columns"][0]["font-style"] = style; - - group_list->addElement(element, ADD_TOP); + childEnable("Activate"); } - - group_list->selectByValue(highlight_id); - - childSetFocus("group list"); -} - -void LLFloaterGroups::enableButtons() -{ - LLCtrlListInterface *group_list = childGetListInterface("group list"); - LLUUID group_id; - if (group_list) + else { - group_id = group_list->getCurrentID(); + childDisable("Activate"); } - if(mType == AGENT_GROUPS) + if (group_id.notNull()) { - if(group_id != gAgent.getGroupID()) - { - childEnable("Activate"); - } - else - { - childDisable("Activate"); - } - if (group_id.notNull()) - { - childEnable("Info"); - childEnable("Leave"); - } - else - { - childDisable("Info"); - childDisable("Leave"); - } - if(gAgent.mGroups.count() < MAX_AGENT_GROUPS) - { - childEnable("Create"); - } - else - { - childDisable("Create"); - } + childEnable("Info"); + childEnable("IM"); + childEnable("Leave"); } else { - childEnable("OK"); + childDisable("Info"); + childDisable("IM"); + childDisable("Leave"); + } + if(gAgent.mGroups.count() < MAX_AGENT_GROUPS) + { + childEnable("Create"); + } + else + { + childDisable("Create"); } } -void LLFloaterGroups::onBtnCreate(void* userdata) +void LLPanelGroups::onBtnCreate(void* userdata) { - LLFloaterGroups* self = (LLFloaterGroups*)userdata; + LLPanelGroups* self = (LLPanelGroups*)userdata; if(self) self->create(); } -void LLFloaterGroups::onBtnActivate(void* userdata) +void LLPanelGroups::onBtnActivate(void* userdata) { - LLFloaterGroups* self = (LLFloaterGroups*)userdata; + LLPanelGroups* self = (LLPanelGroups*)userdata; if(self) self->activate(); } -void LLFloaterGroups::onBtnInfo(void* userdata) +void LLPanelGroups::onBtnInfo(void* userdata) { - LLFloaterGroups* self = (LLFloaterGroups*)userdata; + LLPanelGroups* self = (LLPanelGroups*)userdata; if(self) self->info(); } -void LLFloaterGroups::onBtnLeave(void* userdata) +void LLPanelGroups::onBtnIM(void* userdata) { - LLFloaterGroups* self = (LLFloaterGroups*)userdata; - if(self) self->leave(); + LLPanelGroups* self = (LLPanelGroups*)userdata; + if(self) self->startIM(); } -void LLFloaterGroups::onBtnSearch(void* userdata) +void LLPanelGroups::onBtnLeave(void* userdata) { - LLFloaterGroups* self = (LLFloaterGroups*)userdata; - if(self) self->search(); -} - -void LLFloaterGroups::onBtnOK(void* userdata) -{ - LLFloaterGroups* self = (LLFloaterGroups*)userdata; - if(self) self->ok(); -} - -void LLFloaterGroups::onBtnCancel(void* userdata) -{ - LLFloaterGroups* self = (LLFloaterGroups*)userdata; - if(self) self->close(); + LLPanelGroups* self = (LLPanelGroups*)userdata; + if(self) self->leave(); } -void LLFloaterGroups::onGroupList(LLUICtrl* ctrl, void* userdata) +void LLPanelGroups::onBtnSearch(void* userdata) { - LLFloaterGroups* self = (LLFloaterGroups*)userdata; - if(self) self->highlightGroupList(ctrl); + LLPanelGroups* self = (LLPanelGroups*)userdata; + if(self) self->search(); } -void LLFloaterGroups::create() +void LLPanelGroups::create() { - llinfos << "LLFloaterGroups::create" << llendl; + llinfos << "LLPanelGroups::create" << llendl; LLFloaterGroupInfo::showCreateGroup(NULL); } -void LLFloaterGroups::activate() +void LLPanelGroups::activate() { - llinfos << "LLFloaterGroups::activate" << llendl; + llinfos << "LLPanelGroups::activate" << llendl; LLCtrlListInterface *group_list = childGetListInterface("group list"); LLUUID group_id; if (group_list) @@ -392,9 +323,9 @@ void LLFloaterGroups::activate() gAgent.sendReliableMessage(); } -void LLFloaterGroups::info() +void LLPanelGroups::info() { - llinfos << "LLFloaterGroups::info" << llendl; + llinfos << "LLPanelGroups::info" << llendl; LLCtrlListInterface *group_list = childGetListInterface("group list"); LLUUID group_id; if (group_list && (group_id = group_list->getCurrentID()).notNull()) @@ -403,9 +334,36 @@ void LLFloaterGroups::info() } } -void LLFloaterGroups::leave() +void LLPanelGroups::startIM() +{ + //llinfos << "LLPanelFriends::onClickIM()" << llendl; + LLCtrlListInterface *group_list = childGetListInterface("group list"); + LLUUID group_id; + + if (group_list && (group_id = group_list->getCurrentID()).notNull()) + { + LLGroupData group_data; + if (gAgent.getGroupData(group_id, group_data)) + { + gIMMgr->setFloaterOpen(TRUE); + gIMMgr->addSession( + group_data.mName, + IM_SESSION_GROUP_START, + group_id); + make_ui_sound("UISndStartIM"); + } + else + { + // this should never happen, as starting a group IM session + // relies on you belonging to the group and hence having the group data + make_ui_sound("UISndInvalidOp"); + } + } +} + +void LLPanelGroups::leave() { - llinfos << "LLFloaterGroups::leave" << llendl; + llinfos << "LLPanelGroups::leave" << llendl; LLCtrlListInterface *group_list = childGetListInterface("group list"); LLUUID group_id; if (group_list && (group_id = group_list->getCurrentID()).notNull()) @@ -427,13 +385,13 @@ void LLFloaterGroups::leave() } } -void LLFloaterGroups::search() +void LLPanelGroups::search() { LLFloaterDirectory::showGroups(); } // static -void LLFloaterGroups::callbackLeaveGroup(S32 option, void* userdata) +void LLPanelGroups::callbackLeaveGroup(S32 option, void* userdata) { LLUUID* group_id = (LLUUID*)userdata; if(option == 0 && group_id) @@ -450,25 +408,58 @@ void LLFloaterGroups::callbackLeaveGroup(S32 option, void* userdata) delete group_id; } -void LLFloaterGroups::ok() +void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata) { - llinfos << "LLFloaterGroups::ok" << llendl; - LLCtrlListInterface *group_list = childGetListInterface("group list"); - LLUUID group_id; - if (group_list) + LLPanelGroups* self = (LLPanelGroups*)userdata; + if(self) self->enableButtons(); +} + +void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id) +{ + S32 count = gAgent.mGroups.count(); + LLUUID id; + LLCtrlListInterface *group_list = ctrl->getListInterface(); + if (!group_list) return; + + group_list->operateOnAll(LLCtrlListInterface::OP_DELETE); + + for(S32 i = 0; i < count; ++i) { - group_id = group_list->getCurrentID(); + id = gAgent.mGroups.get(i).mID; + LLGroupData* group_datap = &gAgent.mGroups.get(i); + LLString style = "NORMAL"; + if(highlight_id == id) + { + style = "BOLD"; + } + + LLSD element; + element["id"] = id; + element["columns"][0]["column"] = "name"; + element["columns"][0]["value"] = group_datap->mName; + element["columns"][0]["font"] = "SANSSERIF"; + element["columns"][0]["font-style"] = style; + + group_list->addElement(element, ADD_SORTED); } - if(mOKCallback) + + // add "none" to list at top { - mOKCallback(group_id, mCallbackUserdata); + LLString style = "NORMAL"; + if (highlight_id.isNull()) + { + style = "BOLD"; + } + LLSD element; + element["id"] = LLUUID::null; + element["columns"][0]["column"] = "name"; + element["columns"][0]["value"] = "none"; + element["columns"][0]["font"] = "SANSSERIF"; + element["columns"][0]["font-style"] = style; + + group_list->addElement(element, ADD_TOP); } - close(); + group_list->selectByValue(highlight_id); } -void LLFloaterGroups::highlightGroupList(LLUICtrl*) -{ - llinfos << "LLFloaterGroups::highlightGroupList" << llendl; - enableButtons(); -} diff --git a/linden/indra/newview/llfloatergroups.h b/linden/indra/newview/llfloatergroups.h index 9c51d2f..ed5b8b2 100644 --- a/linden/indra/newview/llfloatergroups.h +++ b/linden/indra/newview/llfloatergroups.h @@ -41,89 +41,80 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include "lluuid.h" -#include "llmap.h" -#include "llevent.h" #include "llfloater.h" +#include class LLUICtrl; class LLTextBox; class LLScrollListCtrl; class LLButton; +class LLFloaterGroupPicker; -class LLFloaterGroups : public LLFloater +class LLFloaterGroupPicker : public LLFloater, public LLUIInstanceMgr { + friend class LLUIInstanceMgr; public: + ~LLFloaterGroupPicker(); + void setSelectCallback( void (*callback)(LLUUID, void*), + void* userdata); + BOOL postBuild(); + +protected: + LLFloaterGroupPicker(const LLSD& seed); + void ok(); + static LLFloaterGroupPicker* findInstance(const LLSD& seed); + static LLFloaterGroupPicker* createInstance(const LLSD& seed); + static void onBtnOK(void* userdata); + static void onBtnCancel(void* userdata); + +protected: + LLUUID mID; + void (*mSelectCallback)(LLUUID id, void* userdata); + void* mCallbackUserdata; + + typedef std::map instance_map_t; + static instance_map_t sInstances; +}; + +class LLPanelGroups : public LLPanel +{ +public: + LLPanelGroups(); + virtual ~LLPanelGroups(); + //LLEventListener /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata); - enum EGroupDialog - { - AGENT_GROUPS, - CHOOSE_ONE - }; - // Call this with an agent id and AGENT_GROUPS for an agent's - // groups, otherwise, call with an object id and SET_OBJECT_GROUP - // when modifying an object. - static LLFloaterGroups* show(const LLUUID& id, EGroupDialog type); - - // Return the instance requested if it already exists. Otherwise, - // return NULL. - static LLFloaterGroups* getInstance(const LLUUID& id); - // clear the group list, and get a fresh set of info. void reset(); - void setOkCallback( void (*callback)(LLUUID, void*), - void* userdata); - - EGroupDialog getType() const { return mType; } - protected: // initialize based on the type BOOL postBuild(); // highlight_id is a group id to highlight - void initAgentGroups(const LLUUID& highlight_id); void enableButtons(); + static void onGroupList(LLUICtrl* ctrl, void* userdata); static void onBtnCreate(void* userdata); static void onBtnActivate(void* userdata); static void onBtnInfo(void* userdata); + static void onBtnIM(void* userdata); static void onBtnLeave(void* userdata); static void onBtnSearch(void* userdata); static void onBtnVote(void* userdata); - static void onBtnOK(void* userdata); - static void onBtnCancel(void* userdata); - static void onGroupList(LLUICtrl* ctrl, void* userdata); static void onDoubleClickGroup(void* userdata); void create(); void activate(); void info(); + void startIM(); void leave(); void search(); void callVote(); - void ok(); - void highlightGroupList(LLUICtrl*); static void callbackLeaveGroup(S32 option, void* userdata); -protected: - LLUUID mID; - - EGroupDialog mType; - - void (*mOKCallback)(LLUUID id, void* userdata); - void* mCallbackUserdata; - -protected: - static LLMap sInstances; - -public: - // do not call these directly - LLFloaterGroups(const std::string& name, const LLRect& rect, const std::string& title, - const LLUUID& id); - virtual ~LLFloaterGroups(); }; diff --git a/linden/indra/newview/llfloaterhtmlhelp.cpp b/linden/indra/newview/llfloaterhtmlhelp.cpp index 9cae4cc..1d6f19e 100644 --- a/linden/indra/newview/llfloaterhtmlhelp.cpp +++ b/linden/indra/newview/llfloaterhtmlhelp.cpp @@ -204,7 +204,7 @@ void LLFloaterHtmlHelp::onClickF1HelpLoadURL(S32 option, void* userdata) // this sucks but there isn't a way to grab an arbitrary string from an XML file // (using llcontroldef strings causes problems if string don't exist) - LLString help_url( "https://support.secondlife.com/" ); + LLString help_url( "http://secondlife.com/support" ); if ( lang == "ja" ) help_url = "http://help.secondlife.com/jp"; else diff --git a/linden/indra/newview/llfloaterimport.cpp b/linden/indra/newview/llfloaterimport.cpp index c60c571..f30f69d 100644 --- a/linden/indra/newview/llfloaterimport.cpp +++ b/linden/indra/newview/llfloaterimport.cpp @@ -56,6 +56,7 @@ #include "pipeline.h" #include "viewer.h" #include "llvieweruictrlfactory.h" +#include "llmd5.h" extern LLInventoryModel gInventory; @@ -588,7 +589,7 @@ void LLFloaterImport::onBtnOK(void*userdata) finishImport(asset_info); } - fp->onClose(false); + fp->close(false); } //----------------------------------------------------------------------------- @@ -597,7 +598,7 @@ void LLFloaterImport::onBtnOK(void*userdata) void LLFloaterImport::onBtnCancel(void*userdata) { LLFloaterImport *fp =(LLFloaterImport*)userdata; - fp->onClose(false); + fp->close(false); } diff --git a/linden/indra/newview/llfloaterinspect.cpp b/linden/indra/newview/llfloaterinspect.cpp index 85cfc4e..c926afa 100644 --- a/linden/indra/newview/llfloaterinspect.cpp +++ b/linden/indra/newview/llfloaterinspect.cpp @@ -74,18 +74,21 @@ BOOL LLFloaterInspect::isVisible() void LLFloaterInspect::show(void* ignored) { - if(sInstance) - { - sInstance->open(); - } - else + // setForceSelection ensures that the pie menu does not deselect things when it + // looses the focus (this can happen with "select own objects only" enabled + // VWR-1471 + BOOL forcesel = gSelectMgr->setForceSelection(TRUE); + + if (!sInstance) // first use { - LLFloaterInspect* self = new LLFloaterInspect; - self->open(); + sInstance = new LLFloaterInspect; } - sInstance->mObjectSelection = gSelectMgr->getSelection(); + sInstance->open(); select_tool(gToolInspect); + gSelectMgr->setForceSelection(forcesel); // restore previouis value + + sInstance->mObjectSelection = gSelectMgr->getSelection(); sInstance->refresh(); } diff --git a/linden/indra/newview/llfloaterland.cpp b/linden/indra/newview/llfloaterland.cpp index 78e5e70..a98c835 100644 --- a/linden/indra/newview/llfloaterland.cpp +++ b/linden/indra/newview/llfloaterland.cpp @@ -42,6 +42,7 @@ #include "llfloateravatarpicker.h" #include "llbutton.h" #include "llcheckboxctrl.h" +#include "llradiogroup.h" #include "llcombobox.h" #include "llfloaterauction.h" #include "llfloateravatarinfo.h" @@ -110,6 +111,14 @@ static const char RAW_HTML[] = "Raw HTML"; static const BOOL BUY_GROUP_LAND = TRUE; static const BOOL BUY_PERSONAL_LAND = FALSE; +// Values for the parcel voice settings radio group +enum +{ + kRadioVoiceChatEstate = 0, + kRadioVoiceChatPrivate = 1, + kRadioVoiceChatDisable = 2 +}; + // Statics LLFloaterLand* LLFloaterLand::sInstance = NULL; LLParcelSelectionObserver* LLFloaterLand::sObserver = NULL; @@ -828,9 +837,20 @@ void LLPanelLandGeneral::draw() // static void LLPanelLandGeneral::onClickSetGroup(void* userdata) { - LLFloaterGroups* fg; - fg = LLFloaterGroups::show(gAgent.getID(), LLFloaterGroups::CHOOSE_ONE); - fg->setOkCallback( cbGroupID, userdata ); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)userdata; + LLFloaterGroupPicker* fg; + + LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); + + fg = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); + fg->setSelectCallback( cbGroupID, userdata ); + + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg); + fg->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(fg); + } } // static @@ -2339,6 +2359,9 @@ BOOL LLPanelLandMedia::postBuild() mCheckSoundLocal = LLUICtrlFactory::getCheckBoxByName(this, "check sound local"); childSetCommitCallback("check sound local", onCommitAny, this); + mRadioVoiceChat = LLUICtrlFactory::getRadioGroupByName(this, "parcel_voice_channel"); + childSetCommitCallback("parcel_voice_channel", onCommitAny, this); + mMusicURLEdit = LLUICtrlFactory::getLineEditorByName(this, "music_url"); childSetCommitCallback("music_url", onCommitAny, this); @@ -2382,6 +2405,9 @@ void LLPanelLandMedia::refresh() mCheckSoundLocal->set(FALSE); mCheckSoundLocal->setEnabled(FALSE); + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatEstate); + mRadioVoiceChat->setEnabled(FALSE); + mMusicURLEdit->setText(""); mMusicURLEdit->setEnabled(FALSE); @@ -2409,6 +2435,20 @@ void LLPanelLandMedia::refresh() mCheckSoundLocal->set( parcel->getSoundLocal() ); mCheckSoundLocal->setEnabled( can_change_media ); + if(parcel->getVoiceEnabled()) + { + if(parcel->getVoiceUseEstateChannel()) + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatEstate); + else + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatPrivate); + } + else + { + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatDisable); + } + + mRadioVoiceChat->setEnabled( can_change_media ); + // don't display urls if you're not able to change it // much requested change in forums so people can't 'steal' urls // NOTE: bug#2009 means this is still vunerable - however, bug @@ -2468,12 +2508,39 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl *ctrl, void *userdata) // Extract data from UI BOOL sound_local = self->mCheckSoundLocal->get(); + int voice_setting = self->mRadioVoiceChat->getSelectedIndex(); std::string music_url = self->mMusicURLEdit->getText(); std::string media_url = self->mMediaURLEdit->getText(); U8 media_auto_scale = self->mMediaAutoScaleCheck->get(); LLUUID media_id = self->mMediaTextureCtrl->getImageAssetID(); + BOOL voice_enabled; + BOOL voice_estate_chan; + + switch(voice_setting) + { + default: + case kRadioVoiceChatEstate: + voice_enabled = TRUE; + voice_estate_chan = TRUE; + break; + case kRadioVoiceChatPrivate: + voice_enabled = TRUE; + voice_estate_chan = FALSE; + break; + case kRadioVoiceChatDisable: + voice_enabled = FALSE; + voice_estate_chan = FALSE; + break; + } + + // Remove leading/trailing whitespace (common when copying/pasting) + LLString::trim(music_url); + LLString::trim(media_url); + // Push data into current parcel + parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, voice_enabled); + parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan); parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local); parcel->setMusicURL(music_url.c_str()); parcel->setMediaURL(media_url.c_str()); diff --git a/linden/indra/newview/llfloaterland.h b/linden/indra/newview/llfloaterland.h index 3cc0b27..6e54d12 100644 --- a/linden/indra/newview/llfloaterland.h +++ b/linden/indra/newview/llfloaterland.h @@ -41,6 +41,7 @@ const F32 CACHE_REFRESH_TIME = 2.5f; class LLTextBox; class LLCheckBoxCtrl; +class LLRadioGroup; class LLComboBox; class LLButton; class LLNameListCtrl; @@ -368,6 +369,7 @@ public: protected: LLCheckBoxCtrl* mCheckSoundLocal; + LLRadioGroup* mRadioVoiceChat; LLLineEditor* mMusicURLEdit; LLLineEditor* mMediaURLEdit; LLTextureCtrl* mMediaTextureCtrl; diff --git a/linden/indra/newview/llfloatermute.cpp b/linden/indra/newview/llfloatermute.cpp index 696f9fe..0f11042 100644 --- a/linden/indra/newview/llfloatermute.cpp +++ b/linden/indra/newview/llfloatermute.cpp @@ -89,6 +89,7 @@ LLFloaterMute::LLFloaterMute() childSetAction("Unmute", onClickRemove, this); mMuteList = LLUICtrlFactory::getScrollListByName(this, "mutes"); + mMuteList->setCommitOnSelectionChange(TRUE); refreshMuteList(); } diff --git a/linden/indra/newview/llfloaternamedesc.cpp b/linden/indra/newview/llfloaternamedesc.cpp index 5f41b13..3f90752 100644 --- a/linden/indra/newview/llfloaternamedesc.cpp +++ b/linden/indra/newview/llfloaternamedesc.cpp @@ -213,7 +213,7 @@ void LLFloaterNameDesc::onBtnOK( void* userdata ) fp->childGetValue("name_form").asString(), fp->childGetValue("description_form").asString(), bitrate, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); - fp->onClose(false); + fp->close(false); } // static @@ -223,5 +223,5 @@ void LLFloaterNameDesc::onBtnOK( void* userdata ) void LLFloaterNameDesc::onBtnCancel( void* userdata ) { LLFloaterNameDesc *fp =(LLFloaterNameDesc *)userdata; - fp->onClose(false); + fp->close(false); } diff --git a/linden/indra/newview/llfloaternewim.cpp b/linden/indra/newview/llfloaternewim.cpp index 1adb37c..844259f 100644 --- a/linden/indra/newview/llfloaternewim.cpp +++ b/linden/indra/newview/llfloaternewim.cpp @@ -208,8 +208,8 @@ void LLFloaterNewIM::onStart(void* userdata) EInstantMessage type; EInstantMessage* t = (EInstantMessage*)item->getUserdata(); if(t) type = (*t); - else type = LLIMView::defaultIMTypeForAgent(item->getUUID()); - gIMView->addSession(name, type, item->getUUID()); + else type = LLIMMgr::defaultIMTypeForAgent(item->getUUID()); + gIMMgr->addSession(name, type, item->getUUID()); make_ui_sound("UISndStartIM"); } @@ -223,7 +223,7 @@ void LLFloaterNewIM::onStart(void* userdata) // static void LLFloaterNewIM::onClickClose(void *userdata) { - gIMView->setFloaterOpen(FALSE); + gIMMgr->setFloaterOpen(FALSE); } @@ -236,7 +236,7 @@ BOOL LLFloaterNewIM::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) { handled = TRUE; // Close talk panel on escape - gIMView->toggle(NULL); + gIMMgr->toggle(NULL); } } diff --git a/linden/indra/newview/llfloaterpostcard.cpp b/linden/indra/newview/llfloaterpostcard.cpp index 82bab03..24344bf 100644 --- a/linden/indra/newview/llfloaterpostcard.cpp +++ b/linden/indra/newview/llfloaterpostcard.cpp @@ -223,7 +223,7 @@ void LLFloaterPostcard::onClickCancel(void* data) { LLFloaterPostcard *self = (LLFloaterPostcard *)data; - self->onClose(false); + self->close(false); } } diff --git a/linden/indra/newview/llfloaterpreference.cpp b/linden/indra/newview/llfloaterpreference.cpp index f7392c4..0b3e856 100644 --- a/linden/indra/newview/llfloaterpreference.cpp +++ b/linden/indra/newview/llfloaterpreference.cpp @@ -54,6 +54,7 @@ #include "llpanelmsgs.h" #include "llpanelweb.h" #include "llprefschat.h" +#include "llprefsvoice.h" #include "llprefsim.h" #include "llresizehandle.h" #include "llresmgr.h" @@ -144,6 +145,10 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainerCommon* tab_container, LLButton mTabContainer->addTabPanel(mPrefsChat->getPanel(), mPrefsChat->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer); mPrefsChat->getPanel()->setDefaultBtn(default_btn); + mPrefsVoice = new LLPrefsVoice(); + mTabContainer->addTabPanel(mPrefsVoice, mPrefsVoice->getLabel(), FALSE, onTabChanged, mTabContainer); + mPrefsVoice->setDefaultBtn(default_btn); + mPrefsIM = new LLPrefsIM(); mTabContainer->addTabPanel(mPrefsIM->getPanel(), mPrefsIM->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer); mPrefsIM->getPanel()->setDefaultBtn(default_btn); @@ -225,8 +230,8 @@ void LLPreferenceCore::apply() mDisplayPanel->apply(); mDisplayPanel2->apply(); mDisplayPanel3->apply(); - mAudioPanel->apply(); mPrefsChat->apply(); + mPrefsVoice->apply(); mPrefsIM->apply(); mMsgPanel->apply(); #if LL_LIBXUL_ENABLED @@ -245,6 +250,7 @@ void LLPreferenceCore::cancel() mDisplayPanel3->cancel(); mAudioPanel->cancel(); mPrefsChat->cancel(); + mPrefsVoice->cancel(); mPrefsIM->cancel(); mMsgPanel->cancel(); #if LL_LIBXUL_ENABLED @@ -388,7 +394,7 @@ void LLFloaterPreference::onBtnOK( void* userdata ) if (fp->canClose()) { fp->apply(); - fp->onClose(false); + fp->close(false); gSavedSettings.saveToFile( gSettingsFileName, TRUE ); diff --git a/linden/indra/newview/llfloaterpreference.h b/linden/indra/newview/llfloaterpreference.h index 1823069..df22c1e 100644 --- a/linden/indra/newview/llfloaterpreference.h +++ b/linden/indra/newview/llfloaterpreference.h @@ -49,6 +49,7 @@ class LLPanelNetwork; class LLPanelWeb; class LLMessageSystem; class LLPrefsChat; +class LLPrefsVoice; class LLPrefsIM; class LLPanelMsgs; class LLScrollListCtrl; @@ -83,6 +84,7 @@ private: LLPanelAudioPrefs *mAudioPanel; // LLPanelDebug *mDebugPanel; LLPrefsChat *mPrefsChat; + LLPrefsVoice *mPrefsVoice; LLPrefsIM *mPrefsIM; LLPanelMsgs *mMsgPanel; LLPanelWeb *mWebPanel; diff --git a/linden/indra/newview/llfloaterregioninfo.cpp b/linden/indra/newview/llfloaterregioninfo.cpp index 70e975e..571bcac 100644 --- a/linden/indra/newview/llfloaterregioninfo.cpp +++ b/linden/indra/newview/llfloaterregioninfo.cpp @@ -1430,11 +1430,21 @@ void LLPanelEstateInfo::addAllowedGroup(S32 option, void* user_data) { if (option != 0) return; - LLFloaterGroups* widget; - widget = LLFloaterGroups::show(gAgent.getID(), LLFloaterGroups::CHOOSE_ONE); + LLPanelEstateInfo* panelp = (LLPanelEstateInfo*)user_data; + + LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); + + LLFloaterGroupPicker* widget; + widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); if (widget) { - widget->setOkCallback(addAllowedGroup2, user_data); + widget->setSelectCallback(addAllowedGroup2, user_data); + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); + widget->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(widget); + } } } @@ -1930,6 +1940,7 @@ BOOL LLPanelEstateInfo::postBuild() initCtrl("deny_anonymous"); initCtrl("deny_identified"); initCtrl("deny_transacted"); + initCtrl("voice_chat_check"); initHelpBtn("estate_manager_help", "HelpEstateEstateManager"); initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime"); @@ -1939,6 +1950,7 @@ BOOL LLPanelEstateInfo::postBuild() initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); initHelpBtn("allow_group_help", "HelpEstateAllowGroup"); initHelpBtn("ban_resident_help", "HelpEstateBanResident"); + initHelpBtn("voice_chat_help", "HelpEstateVoiceChat"); // set up the use global time checkbox childSetCommitCallback("use_global_time_check", onChangeUseGlobalTime, this); @@ -2104,6 +2116,9 @@ void LLPanelEstateInfo::setEstateFlags(U32 flags) { childSetValue("externally_visible_check", LLSD(flags & REGION_FLAGS_EXTERNALLY_VISIBLE ? TRUE : FALSE) ); childSetValue("fixed_sun_check", LLSD(flags & REGION_FLAGS_SUN_FIXED ? TRUE : FALSE) ); + childSetValue( + "voice_chat_check", + LLSD(flags & REGION_FLAGS_ALLOW_VOICE ? TRUE : FALSE)); childSetValue("allow_direct_teleport", LLSD(flags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT ? TRUE : FALSE) ); childSetValue("deny_anonymous", LLSD(flags & REGION_FLAGS_DENY_ANONYMOUS ? TRUE : FALSE) ); childSetValue("deny_identified", LLSD(flags & REGION_FLAGS_DENY_IDENTIFIED ? TRUE : FALSE) ); @@ -2119,6 +2134,11 @@ U32 LLPanelEstateInfo::computeEstateFlags() { flags |= REGION_FLAGS_EXTERNALLY_VISIBLE; } + + if ( childGetValue("voice_chat_check").asBoolean() ) + { + flags |= REGION_FLAGS_ALLOW_VOICE; + } if (childGetValue("allow_direct_teleport").asBoolean()) { diff --git a/linden/indra/newview/llfloaterscriptdebug.cpp b/linden/indra/newview/llfloaterscriptdebug.cpp index 5ad2dc9..82f5ce8 100644 --- a/linden/indra/newview/llfloaterscriptdebug.cpp +++ b/linden/indra/newview/llfloaterscriptdebug.cpp @@ -51,10 +51,12 @@ LLFloaterScriptDebug* LLFloaterScriptDebug::sInstance = NULL; // // Member Functions // -LLFloaterScriptDebug::LLFloaterScriptDebug() -: LLMultiFloater() +LLFloaterScriptDebug::LLFloaterScriptDebug() : + LLMultiFloater() { - + // avoid resizing of the window to match + // the initial size of the tabbed-childs, whenever a tab is opened or closed + mAutoResize = FALSE; } LLFloaterScriptDebug::~LLFloaterScriptDebug() @@ -110,6 +112,9 @@ LLFloater* LLFloaterScriptDebug::addOutputWindow(const LLUUID &object_id) } LLFloater::setFloaterHost(NULL); + // Tabs sometimes overlap resize handle + sInstance->moveResizeHandlesToFront(); + return floaterp; } diff --git a/linden/indra/newview/llfloatersnapshot.cpp b/linden/indra/newview/llfloatersnapshot.cpp index 5008509..8b104a3 100644 --- a/linden/indra/newview/llfloatersnapshot.cpp +++ b/linden/indra/newview/llfloatersnapshot.cpp @@ -125,7 +125,7 @@ public: void updateSnapshot(BOOL new_snapshot); LLFloaterPostcard* savePostcard(); void saveTexture(); - void saveLocal(); + BOOL saveLocal(); static void onIdle( void* snapshot_preview ); @@ -381,8 +381,7 @@ void LLSnapshotLivePreview::draw() F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME); // draw "shine" effect - LLGLEnable scissor_test(GL_SCISSOR_TEST); - LLUI::setScissorRegionLocal(LLRect(0, mRect.getHeight(), mRect.getWidth(), 0)); + LLLocalClipRect clip(getLocalRect()); { // draw diagonal stripe with gradient that passes over screen S32 x1 = gViewerWindow->getWindowWidth() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f))); @@ -698,9 +697,9 @@ void LLSnapshotLivePreview::saveTexture() gViewerStats->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); } -void LLSnapshotLivePreview::saveLocal() +BOOL LLSnapshotLivePreview::saveLocal() { - gViewerWindow->saveImageNumbered(mRawImage); + return gViewerWindow->saveImageNumbered(mRawImage); } ///---------------------------------------------------------------------------- @@ -959,6 +958,8 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) if (previewp) { + BOOL succeeded = TRUE; // Only used for saveLocal for now + if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) { LLFloaterPostcard* floater = previewp->savePostcard(); @@ -977,21 +978,24 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) } else { - previewp->saveLocal(); + succeeded = previewp->saveLocal(); } if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) { view->close(); - // only plays sound and anim when keeping a snapshot, and closing the snapshot UI - gViewerWindow->playSnapshotAnimAndSound(); + // only plays sound and anim when keeping a snapshot, and closing the snapshot UI, + // and only if the save succeeded (i.e. was not canceled) + if (succeeded) + { + gViewerWindow->playSnapshotAnimAndSound(); + } } else { checkAutoSnapshot(previewp); } } - } // static diff --git a/linden/indra/newview/llfloatertest.cpp b/linden/indra/newview/llfloatertest.cpp index c5e353a..6719a38 100644 --- a/linden/indra/newview/llfloatertest.cpp +++ b/linden/indra/newview/llfloatertest.cpp @@ -387,3 +387,10 @@ LLFloaterTest::~LLFloaterTest() { delete &impl; } + +//--------------------------------------------------------------------------- + +LLFloaterSimple::LLFloaterSimple(const std::string& xml_filename) +{ + gUICtrlFactory->buildFloater(this, xml_filename); +} diff --git a/linden/indra/newview/llfloatertest.h b/linden/indra/newview/llfloatertest.h index 93869ef..afb0683 100644 --- a/linden/indra/newview/llfloatertest.h +++ b/linden/indra/newview/llfloatertest.h @@ -30,6 +30,8 @@ #ifndef LL_LLFLOATERTEST_H #define LL_LLFLOATERTEST_H +#include "llfloater.h" + class LLFloaterTestImpl; class LLFloaterTest @@ -44,4 +46,10 @@ private: LLFloaterTestImpl& impl; }; +class LLFloaterSimple : public LLFloater +{ +public: + LLFloaterSimple(const std::string& filename); +}; + #endif diff --git a/linden/indra/newview/llfloatertools.cpp b/linden/indra/newview/llfloatertools.cpp index 3748131..df5d488 100644 --- a/linden/indra/newview/llfloatertools.cpp +++ b/linden/indra/newview/llfloatertools.cpp @@ -73,7 +73,6 @@ #include "llviewerparcelmgr.h" #include "llviewerwindow.h" #include "llviewercontrol.h" -#include "llvolumesliderctrl.h" #include "viewer.h" #include "llvieweruictrlfactory.h" @@ -195,7 +194,6 @@ BOOL LLFloaterTools::postBuild() childSetAction("button land",LLFloaterTools::setEditTool, (void*)gToolParcel); mTextStatus = LLUICtrlFactory::getTextBoxByName(this,"text status"); mRadioZoom = LLUICtrlFactory::getCheckBoxByName(this,"radio zoom"); - mSliderZoom = LLViewerUICtrlFactory::getVolumeSliderByName(this,"slider zoom"); childSetCommitCallback("slider zoom",commit_slider_zoom,this); mRadioOrbit = LLUICtrlFactory::getCheckBoxByName(this,"radio orbit"); childSetCommitCallback("radio orbit",commit_radio_orbit,this); @@ -496,8 +494,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) mRadioZoom ->setVisible( focus_visible ); mRadioOrbit ->setVisible( focus_visible ); mRadioPan ->setVisible( focus_visible ); - mSliderZoom ->setVisible( focus_visible ); - + childSetVisible("slider zoom", focus_visible); + mRadioZoom ->set( !gCameraBtnOrbit && !gCameraBtnPan && !(mask == MASK_ORBIT) && @@ -514,7 +512,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) (mask == (MASK_PAN | MASK_ALT)) ); // multiply by correction factor because volume sliders go [0, 0.5] - mSliderZoom ->setValue( gAgent.getCameraZoomFraction() * 0.5f); + childSetValue( "slider zoom", gAgent.getCameraZoomFraction() * 0.5f); // Move buttons BOOL move_visible = (tool == gToolGrab); @@ -853,9 +851,8 @@ void commit_radio_pan(LLUICtrl *, void*) void commit_slider_zoom(LLUICtrl *ctrl, void*) { - LLVolumeSliderCtrl* slider = (LLVolumeSliderCtrl*)ctrl; // renormalize value, since max "volume" level is 0.5 for some reason - F32 zoom_level = (F32)slider->getValue().asReal() * 2.f; // / 0.5f; + F32 zoom_level = (F32)ctrl->getValue().asReal() * 2.f; // / 0.5f; gAgent.setCameraZoomFraction(zoom_level); } diff --git a/linden/indra/newview/llfloatertools.h b/linden/indra/newview/llfloatertools.h index 27d7f56..ae70a04 100644 --- a/linden/indra/newview/llfloatertools.h +++ b/linden/indra/newview/llfloatertools.h @@ -44,7 +44,6 @@ class LLPanelContents; class LLPanelFace; class LLPanelLandInfo; class LLComboBox; -class LLVolumeSliderCtrl; class LLParcelSelection; class LLObjectSelection; @@ -120,7 +119,6 @@ public: LLCheckBoxCtrl *mRadioOrbit; LLCheckBoxCtrl *mRadioZoom; LLCheckBoxCtrl *mRadioPan; - LLVolumeSliderCtrl *mSliderZoom; // Move buttons LLCheckBoxCtrl *mRadioMove; diff --git a/linden/indra/newview/llfloatervoicewizard.cpp b/linden/indra/newview/llfloatervoicewizard.cpp new file mode 100644 index 0000000..879cb6d --- /dev/null +++ b/linden/indra/newview/llfloatervoicewizard.cpp @@ -0,0 +1,444 @@ +/** + * @file llfloatervoicewizard.cpp + * @author Richard Nelson + * @brief Voice communication set-up wizard + * + * Copyright (c) 2007-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatervoicewizard.h" + +#include "llagent.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "llfocusmgr.h" +#include "lliconctrl.h" +#include "llprefsvoice.h" +#include "llsliderctrl.h" +#include "llviewercontrol.h" +#include "llvieweruictrlfactory.h" +#include "llvoiceclient.h" +#include "llimpanel.h" + +LLFloaterVoiceWizard::LLFloaterVoiceWizard(const LLSD& seed) : LLFloater("floater_voice_wizard"), mDevicePanel(NULL) +{ + mFactoryMap["device_settings"] = LLCallbackMap(createPanelDeviceSettings, this); + // do not automatically open singleton floaters (as result of getInstance()) + BOOL no_open = FALSE; + gUICtrlFactory->buildFloater(this, "floater_voice_wizard.xml", &mFactoryMap, no_open); + + mLogic = new LLPrefsVoiceLogic(this); + center(); +} + +LLFloaterVoiceWizard::~LLFloaterVoiceWizard() +{ + delete mLogic; + mLogic = NULL; +} + +BOOL LLFloaterVoiceWizard::postBuild() +{ + childSetAction("next_btn", onClickNext, this); + childSetAction("back_btn", onClickBack, this); + childSetAction("ok_btn", onClickOK, this); + childSetAction("cancel_btn", onClickCancel, this); + + childSetCommitCallback("voice_enable", onCommitVoiceEnable, this); + + return TRUE; +} + +void LLFloaterVoiceWizard::draw() +{ + mLogic->refresh(); + if (mDevicePanel) + { + mDevicePanel->refresh(); + } + + LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName(this, "wizard_tabs"); + + if (tabs) + { + // if on first tab, disable back button, etc + if (tabs->getCurrentPanelIndex() == 0) + { + if (gSavedSettings.getBOOL("EnableVoiceChat")) + { + childSetEnabled("next_btn", TRUE); + setDefaultBtn(gUICtrlFactory->getButtonByName(this, "next_btn")); + } + else + { + childSetEnabled("next_btn", FALSE); + setDefaultBtn(gUICtrlFactory->getButtonByName(this, "ok_btn")); + } + childSetEnabled("back_btn", FALSE); + } + else + { + // if on any tab but the last, enable the next button + if (tabs->getCurrentPanelIndex() < tabs->getTabCount() - 1) + { + childSetEnabled("next_btn", TRUE); + setDefaultBtn(gUICtrlFactory->getButtonByName(this, "next_btn")); + } + else + { + childSetEnabled("next_btn", FALSE); + setDefaultBtn(gUICtrlFactory->getButtonByName(this, "ok_btn")); + } + childSetEnabled("back_btn", TRUE); + } + } + + // because we can simultaneously change voice settings from the preferences UI + // we need to stay in sync + childSetValue("voice_enable", gSavedSettings.getBOOL("EnableVoiceChat") ? "1" : "0"); + + // show appropriate text on first tab + childSetVisible("voice_intro_text3", !gSavedSettings.getBOOL("EnableVoiceChat")); + childSetVisible("voice_intro_text4", gSavedSettings.getBOOL("EnableVoiceChat")); + + LLFloater::draw(); +} + +void LLFloaterVoiceWizard::onOpen() +{ + // put voice client in "tuning" mode + gVoiceClient->tuningStart(); + //LLVoiceChannel::suspend(); + LLFloater::onOpen(); +} + +void LLFloaterVoiceWizard::onClose(bool app_quitting) +{ + gVoiceClient->tuningStop(); + //LLVoiceChannel::resume(); + LLFloater::onClose(app_quitting); +} + + +// static +void LLFloaterVoiceWizard::onClickNext(void *user_data) +{ + LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName((LLFloater*)user_data, "wizard_tabs"); + if (tabs) + { + tabs->selectNextTab(); + } +} + +// static +void LLFloaterVoiceWizard::onClickBack(void *user_data) +{ + LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName((LLFloater*)user_data, "wizard_tabs"); + if (tabs) + { + tabs->selectPrevTab(); + } +} + +// static +void LLFloaterVoiceWizard::onClickOK(void *user_data) +{ + LLFloaterVoiceWizard* self = (LLFloaterVoiceWizard*)user_data; + + // propagate tuning mic volume to actual mic volume + self->mLogic->apply(); + if (self->mDevicePanel) + { + self->mDevicePanel->apply(); + } + self->close(); +} + +// static +void LLFloaterVoiceWizard::onClickCancel(void *user_data) +{ + LLFloaterVoiceWizard* self = (LLFloaterVoiceWizard*)user_data; + + self->mLogic->cancel(); + if (self->mDevicePanel) + { + self->mDevicePanel->cancel(); + } + self->close(); +} + +// static +void LLFloaterVoiceWizard::onCommitVoiceEnable(LLUICtrl* ctrl, void* user_data) +{ + gSavedSettings.setBOOL("EnableVoiceChat", ctrl->getValue().asInteger()); +} + +// static +void* LLFloaterVoiceWizard::createPanelDeviceSettings(void* user_data) +{ + LLFloaterVoiceWizard* floaterp = (LLFloaterVoiceWizard*)user_data; + floaterp->mDevicePanel = new LLPanelDeviceSettings(); + return floaterp->mDevicePanel; +} + + +// +// LLPanelDeviceSettings +// + +LLPanelDeviceSettings::LLPanelDeviceSettings() +{ + mCtrlInputDevices = NULL; + mCtrlOutputDevices = NULL; + mInputDevice = gSavedSettings.getString("VoiceInputAudioDevice"); + mOutputDevice = gSavedSettings.getString("VoiceOutputAudioDevice"); + mDevicesUpdated = FALSE; + + // grab "live" mic volume level + mMicVolume = gSavedSettings.getF32("AudioLevelMic"); + + // ask for new device enumeration + gVoiceClient->refreshDeviceLists(); +} + +LLPanelDeviceSettings::~LLPanelDeviceSettings() +{ +} + +BOOL LLPanelDeviceSettings::postBuild() +{ + LLSlider* volume_slider = gUICtrlFactory->getSliderBarByName(this, "mic_volume_slider"); + if (volume_slider) + { + // set mic volume tuning slider based on last mic volume setting + volume_slider->setValue(mMicVolume); + } + + return TRUE; +} + +void LLPanelDeviceSettings::draw() +{ + // let user know that volume indicator is not yet available + childSetVisible("wait_text", !gVoiceClient->inTuningMode()); + + LLPanel::draw(); + + F32 voice_power = gVoiceClient->tuningGetEnergy(); + S32 discrete_power = 0; + + if (!gVoiceClient->inTuningMode()) + { + discrete_power = 0; + } + else + { + discrete_power = llmin(4, llfloor((voice_power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 4.f)); + } + + if (gVoiceClient->inTuningMode()) + { + const S32 GAP = 5; + S32 cur_x = 100; + S32 cur_y = 15; + + for(S32 power_bar_idx = 0; power_bar_idx < 5; power_bar_idx++) + { + if (power_bar_idx < discrete_power) + { + LLColor4 color = (power_bar_idx >= 3) ? gSavedSettings.getColor4("OverdrivenColor") : gSavedSettings.getColor4("SpeakingColor"); + gl_rect_2d(cur_x, cur_y + 20, cur_x + 20, cur_y, color, TRUE); + } + gl_rect_2d(cur_x, cur_y + 20, cur_x + 20, cur_y, LLColor4::grey, FALSE); + cur_x += 20 + GAP; + } + } +} + +void LLPanelDeviceSettings::apply() +{ + std::string s; + if(mCtrlInputDevices) + { + s = mCtrlInputDevices->getSimple(); + gSavedSettings.setString("VoiceInputAudioDevice", s); + } + + if(mCtrlOutputDevices) + { + s = mCtrlOutputDevices->getSimple(); + gSavedSettings.setString("VoiceOutputAudioDevice", s); + } + + // assume we are being destroyed by closing our embedding window + gSavedSettings.setF32("AudioLevelMic", mMicVolume); +} + +void LLPanelDeviceSettings::cancel() +{ + gSavedSettings.setString("VoiceInputAudioDevice", mInputDevice); + gSavedSettings.setString("VoiceOutputAudioDevice", mOutputDevice); + + if(mCtrlInputDevices) + mCtrlInputDevices->setSimple(mInputDevice); + + if(mCtrlOutputDevices) + mCtrlOutputDevices->setSimple(mOutputDevice); +} + +void LLPanelDeviceSettings::refresh() +{ + //grab current volume + LLSlider* volume_slider = gUICtrlFactory->getSliderBarByName(this, "mic_volume_slider"); + if (volume_slider) + { + // set mic volume tuning slider based on last mic volume setting + mMicVolume = (F32)volume_slider->getValue().asReal(); + gVoiceClient->tuningSetMicVolume(mMicVolume); + } + + // Fill in popup menus + mCtrlInputDevices = LLUICtrlFactory::getComboBoxByName(this, "voice_input_device"); + mCtrlOutputDevices = LLUICtrlFactory::getComboBoxByName(this, "voice_output_device"); + + if(!gVoiceClient->deviceSettingsAvailable()) + { + // The combo boxes are disabled, since we can't get the device settings from the daemon just now. + // Put the currently set default (ONLY) in the box, and select it. + if(mCtrlInputDevices) + { + mCtrlInputDevices->removeall(); + mCtrlInputDevices->add( mInputDevice, ADD_BOTTOM ); + mCtrlInputDevices->setSimple(mInputDevice); + } + if(mCtrlOutputDevices) + { + mCtrlOutputDevices->removeall(); + mCtrlOutputDevices->add( mOutputDevice, ADD_BOTTOM ); + mCtrlOutputDevices->setSimple(mOutputDevice); + } + } + else if (!mDevicesUpdated) + { + LLVoiceClient::deviceList *devices; + + LLVoiceClient::deviceList::iterator iter; + + if(mCtrlInputDevices) + { + mCtrlInputDevices->removeall(); + mCtrlInputDevices->add( "Default", ADD_BOTTOM ); + + devices = gVoiceClient->getCaptureDevices(); + for(iter=devices->begin(); iter != devices->end(); iter++) + { + mCtrlInputDevices->add( *iter, ADD_BOTTOM ); + } + + if(!mCtrlInputDevices->setSimple(mInputDevice)) + { + mCtrlInputDevices->setSimple("Default"); + } + } + + if(mCtrlOutputDevices) + { + mCtrlOutputDevices->removeall(); + mCtrlOutputDevices->add( "Default", ADD_BOTTOM ); + + devices = gVoiceClient->getRenderDevices(); + for(iter=devices->begin(); iter != devices->end(); iter++) + { + mCtrlOutputDevices->add( *iter, ADD_BOTTOM ); + } + + if(!mCtrlOutputDevices->setSimple(mOutputDevice)) + { + mCtrlOutputDevices->setSimple("Default"); + } + } + mDevicesUpdated = TRUE; + } +} + +// +// LLFloaterDeviceSettings +// + +LLFloaterDeviceSettings::LLFloaterDeviceSettings(const LLSD& seed) : LLFloater("floater_device_settings"), mDevicePanel(NULL) +{ + mFactoryMap["device_settings"] = LLCallbackMap(createPanelDeviceSettings, this); + gUICtrlFactory->buildFloater(this, "floater_device_settings.xml", &mFactoryMap); + center(); +} + +void LLFloaterDeviceSettings::onOpen() +{ + // put voice client in "tuning" mode + gVoiceClient->tuningStart(); + //LLVoiceChannel::suspend(); + LLFloater::onOpen(); +} + +void LLFloaterDeviceSettings::onClose(bool app_quitting) +{ + gVoiceClient->tuningStop(); + //LLVoiceChannel::resume(); + setVisible(FALSE); +} + +void LLFloaterDeviceSettings::apply() +{ + if (mDevicePanel) + { + mDevicePanel->apply(); + } +} + +void LLFloaterDeviceSettings::cancel() +{ + if (mDevicePanel) + { + mDevicePanel->cancel(); + } +} + +void LLFloaterDeviceSettings::draw() +{ + if (mDevicePanel) + { + mDevicePanel->refresh(); + } + LLFloater::draw(); +} + +// static +void* LLFloaterDeviceSettings::createPanelDeviceSettings(void* user_data) +{ + LLFloaterDeviceSettings* floaterp = (LLFloaterDeviceSettings*)user_data; + floaterp->mDevicePanel = new LLPanelDeviceSettings(); + return floaterp->mDevicePanel; +} diff --git a/linden/indra/newview/llfloatervoicewizard.h b/linden/indra/newview/llfloatervoicewizard.h new file mode 100644 index 0000000..bd9ce80 --- /dev/null +++ b/linden/indra/newview/llfloatervoicewizard.h @@ -0,0 +1,100 @@ +/** + * @file llfloatervoicewizard.h + * @author Richard Nelson + * @brief Voice communication set-up wizard + * + * Copyright (c) 2001-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LL_LLFLOATERVOICEWIZARD_H +#define LL_LLFLOATERVOICEWIZARD_H + +#include "llfloater.h" + +class LLPrefsVoiceLogic; +class LLPanelDeviceSettings; + +class LLFloaterVoiceWizard +: public LLFloater, public LLUISingleton +{ +public: + LLFloaterVoiceWizard(const LLSD& seed); + virtual ~LLFloaterVoiceWizard(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void onOpen(); + /*virtual*/ void onClose(bool app_quitting); + +protected: + static void onClickNext(void *user_data); + static void onClickBack(void *user_data); + static void onClickOK(void *user_data); + static void onClickCancel(void *user_data); + static void onCommitVoiceEnable(LLUICtrl* ctrl, void* user_data); + static void* createPanelDeviceSettings(void* user_data); + +protected: + LLPrefsVoiceLogic* mLogic; + LLPanelDeviceSettings* mDevicePanel; +}; + +class LLPanelDeviceSettings : public LLPanel +{ +public: + LLPanelDeviceSettings(); + ~LLPanelDeviceSettings(); + + /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild(); + void apply(); + void cancel(); + void refresh(); + +protected: + F32 mMicVolume; + std::string mInputDevice; + std::string mOutputDevice; + LLComboBox *mCtrlInputDevices; + LLComboBox *mCtrlOutputDevices; + BOOL mDevicesUpdated; +}; + +class LLFloaterDeviceSettings : public LLFloater, public LLUISingleton +{ +public: + LLFloaterDeviceSettings(const LLSD& seed); + /*virtual*/ void onOpen(); + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void draw(); + void apply(); + void cancel(); + +protected: + static void* createPanelDeviceSettings(void* user_data); + + LLPanelDeviceSettings* mDevicePanel; +}; + +#endif // LL_LLFLOATERVOICEWIZARD_H diff --git a/linden/indra/newview/llfloaterworldmap.cpp b/linden/indra/newview/llfloaterworldmap.cpp index dc42a40..ccd252b 100644 --- a/linden/indra/newview/llfloaterworldmap.cpp +++ b/linden/indra/newview/llfloaterworldmap.cpp @@ -179,6 +179,8 @@ LLFloaterWorldMap::LLFloaterWorldMap() mCompletingRegionName(""), mWaitingForTracker(FALSE), mExactMatch(FALSE), + mIsClosing(FALSE), + mSetToUserPosition(TRUE), mTrackedLocation(0,0,0), mTrackedStatus(LLTracker::TRACKING_NOTHING) { @@ -355,6 +357,9 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) gFloaterWorldMap->buildAvatarIDList(); gFloaterWorldMap->buildLandmarkIDLists(); + + // If nothing is being tracked, set flag so the user position will be found + gFloaterWorldMap->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } if (center_on_target) @@ -517,7 +522,7 @@ void LLFloaterWorldMap::draw() childSetEnabled("Teleport", (BOOL)tracking_status); // childSetEnabled("Clear", (BOOL)tracking_status); childSetEnabled("Show Destination", (BOOL)tracking_status || gWorldMap->mIsTrackingUnknownLocation); - childSetEnabled("copy_slurl", (BOOL)tracking_status); + childSetEnabled("copy_slurl", (mSLURL.size() > 0) ); setMouseOpaque(TRUE); mDragHandle->setMouseOpaque(TRUE); @@ -661,7 +666,8 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) return; } - LLString sim_name = gWorldMap->simNameFromPosGlobal( pos_global ); + LLString sim_name; + gWorldMap->simNameFromPosGlobal( pos_global, sim_name ); F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); LLString full_name = llformat("%s (%d, %d, %d)", @@ -682,15 +688,51 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) void LLFloaterWorldMap::updateLocation() { + bool gotSimName; + + LLTracker::ETrackingStatus status = LLTracker::getTrackingStatus(); + // These values may get updated by a message, so need to check them every frame // The fields may be changed by the user, so only update them if the data changes LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); if (pos_global.isExactlyZero()) { + LLVector3d agentPos = gAgent.getPositionGlobal(); + + // Set to avatar's current postion if nothing is selected + if ( status == LLTracker::TRACKING_NOTHING && mSetToUserPosition ) + { + // Make sure we know where we are before setting the current user position + LLString agent_sim_name; + gotSimName = gWorldMap->simNameFromPosGlobal( agentPos, agent_sim_name ); + if ( gotSimName ) + { + mSetToUserPosition = FALSE; + + // Fill out the location field + childSetValue("location", agent_sim_name); + + // Figure out where user is + LLVector3d agentPos = gAgent.getPositionGlobal(); + + S32 agent_x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) ); + S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) ); + S32 agent_z = llround( (F32)agentPos.mdV[VZ] ); + + childSetValue("spin x", LLSD(agent_x) ); + childSetValue("spin y", LLSD(agent_y) ); + childSetValue("spin z", LLSD(agent_z) ); + + // Set the current SLURL + mSLURL = LLWeb::escapeURL( llformat("http://slurl.com/secondlife/%s/%d/%d/%d", + agent_sim_name.c_str(), agent_x, agent_y, agent_z) ); + } + } + return; // invalid location } - LLTracker::ETrackingStatus status = LLTracker::getTrackingStatus(); - LLString sim_name = gWorldMap->simNameFromPosGlobal( pos_global ); + LLString sim_name; + gotSimName = gWorldMap->simNameFromPosGlobal( pos_global, sim_name ); if ((status != LLTracker::TRACKING_NOTHING) && (status != mTrackedStatus || pos_global != mTrackedLocation || sim_name != mTrackedSimName)) { @@ -717,8 +759,16 @@ void LLFloaterWorldMap::updateLocation() childSetValue("spin y", LLSD(region_y) ); childSetValue("spin z", LLSD((F32)pos_global.mdV[VZ]) ); - mSLURL = LLWeb::escapeURL(llformat("http://slurl.com/secondlife/%s/%d/%d/%d", - sim_name.c_str(), llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ]))); + // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL + if ( gotSimName ) + { + mSLURL = LLWeb::escapeURL(llformat("http://slurl.com/secondlife/%s/%d/%d/%d", + sim_name.c_str(), llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ]))); + } + else + { // Empty SLURL will disable the "Copy SLURL to clipboard" button + mSLURL = ""; + } } } @@ -1102,6 +1152,9 @@ void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) self->trackLandmark( item_id); onShowTargetBtn(self); + + // Reset to user postion if nothing is tracked + self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } // static @@ -1153,6 +1206,10 @@ void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata ) self->trackAvatar(new_avatar_id, name); onShowTargetBtn(self); } + else + { // Reset to user postion if nothing is tracked + self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); + } } // static @@ -1208,6 +1265,8 @@ void LLFloaterWorldMap::onClearBtn(void* data) self->mTrackedStatus = LLTracker::TRACKING_NOTHING; LLTracker::stopTracking((void *)(intptr_t)TRUE); gWorldMap->mIsTrackingUnknownLocation = FALSE; + self->mSLURL = ""; // Clear the SLURL since it's invalid + self->mSetToUserPosition = TRUE; // Revert back to the current user position } // static @@ -1226,6 +1285,10 @@ void LLFloaterWorldMap::onShowTargetBtn(void* data) void LLFloaterWorldMap::onShowAgentBtn(void* data) { LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate + + // Set flag so user's location will be displayed if not tracking anything else + LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; + self->mSetToUserPosition = TRUE; } // static diff --git a/linden/indra/newview/llfloaterworldmap.h b/linden/indra/newview/llfloaterworldmap.h index f383754..d2a4e6f 100644 --- a/linden/indra/newview/llfloaterworldmap.h +++ b/linden/indra/newview/llfloaterworldmap.h @@ -176,6 +176,7 @@ protected: BOOL mExactMatch; BOOL mIsClosing; + BOOL mSetToUserPosition; LLVector3d mTrackedLocation; LLTracker::ETrackingStatus mTrackedStatus; diff --git a/linden/indra/newview/llfolderview.cpp b/linden/indra/newview/llfolderview.cpp index 36d0b40..f3c6ace 100644 --- a/linden/indra/newview/llfolderview.cpp +++ b/linden/indra/newview/llfolderview.cpp @@ -568,16 +568,15 @@ void LLFolderViewItem::rename(const LLString& new_name) if( !new_name.empty() ) { mLabel = new_name.c_str(); - BOOL is_renamed = TRUE; if( mListener ) { - is_renamed = mListener->renameItem(new_name); - } - if(mParentFolder && is_renamed) - { - mParentFolder->resort(this); + mListener->renameItem(new_name); + + if(mParentFolder) + { + mParentFolder->resort(this); + } } - //refresh(); } } @@ -2990,7 +2989,10 @@ void LLFolderView::sanitizeSelection() // store off current item in case it is automatically deselected // and we want to preserve context LLFolderViewItem* original_selected_item = getCurSelectedItem(); - + + // Cache "Show all folders" filter setting + BOOL show_all_folders = (getRoot()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); + std::vector items_to_remove; selected_items_t::iterator item_iter; for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) @@ -3001,10 +3003,20 @@ void LLFolderView::sanitizeSelection() BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); - while(parent_folder) + if ( parent_folder ) { - visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); + if ( show_all_folders ) + { // "Show all folders" is on, so this folder is visible + visible = TRUE; + } + else + { // Move up through parent folders and see what's visible + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } + } } // deselect item if any ancestor is closed or didn't pass filter requirements. @@ -3020,7 +3032,7 @@ void LLFolderView::sanitizeSelection() for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) { LLFolderViewItem* other_item = *other_item_iter; - for(LLFolderViewFolder* parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) + for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) { if (parent_folder == item) { @@ -3359,19 +3371,30 @@ void LLFolderView::openSelectedItems( void ) { S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); - LLMultiPreview* multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100)); - - LLFloater::setFloaterHost(multi_previewp); + gFloaterView->getNewFloaterPosition(&left, &top); + LLMultiProperties* multi_propertiesp = new LLMultiProperties(LLRect(left, top, left + 300, top - 100)); selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - (*item_it)->open(); /* Flawfinder: ignore */ + // IT_{OBJECT,ATTACHMENT} creates LLProperties + // floaters; others create LLPreviews. Put + // each one in the right type of container. + LLFolderViewEventListener* listener = (*item_it)->getListener(); + bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + if (is_prop) + LLFloater::setFloaterHost(multi_propertiesp); + else + LLFloater::setFloaterHost(multi_previewp); + (*item_it)->open(); } LLFloater::setFloaterHost(NULL); - multi_previewp->open(); /* Flawfinder: ignore */ + // *NOTE: LLMulti* will safely auto-delete when open'd + // without any children. + multi_previewp->open(); + multi_propertiesp->open(); } } } @@ -4665,7 +4688,7 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) BOOL LLInventoryFilter::isSinceLogoff() { - return mFilterOps.mMinDate == mLastLogoff && mFilterOps.mMaxDate == U32_MAX; + return (mFilterOps.mMinDate == mLastLogoff) && (mFilterOps.mMaxDate == U32_MAX); } void LLInventoryFilter::setHoursAgo(U32 hours) @@ -4966,28 +4989,48 @@ void LLInventoryFilter::toLLSD(LLSD& data) data["permissions"] = (LLSD::Integer)getFilterPermissions(); data["substring"] = (LLSD::String)getFilterSubString(); data["sort_order"] = (LLSD::Integer)getSortOrder(); + data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); } void LLInventoryFilter::fromLLSD(LLSD& data) { if(data.has("filter_types")) + { setFilterTypes((U32)data["filter_types"].asInteger()); + } if(data.has("min_date") && data.has("max_date")) + { setDateRange((U32)data["min_date"].asInteger(), (U32)data["max_date"].asInteger()); + } if(data.has("hours_ago")) + { setHoursAgo((U32)data["hours_ago"].asInteger()); + } if(data.has("show_folder_state")) + { setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); + } if(data.has("permissions")) + { setFilterPermissions((PermissionMask)data["permissions"].asInteger()); + } if(data.has("substring")) + { setFilterSubString(LLString(data["substring"].asString())); + } if(data.has("sort_order")) + { setSortOrder((U32)data["sort_order"].asInteger()); + } + + if(data.has("since_logoff")) + { + setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); + } } diff --git a/linden/indra/newview/llframestatview.cpp b/linden/indra/newview/llframestatview.cpp index af9162d..c489caa 100644 --- a/linden/indra/newview/llframestatview.cpp +++ b/linden/indra/newview/llframestatview.cpp @@ -378,6 +378,12 @@ void LLFrameStatView::draw() void LLFrameStatView::addStat(LLStat *statp, const char *label, const LLColor4 &color) { + if( mNumStats >= MAX_STATS ) + { + llwarns << "LLFrameStatView::addStat - too many stats!" << llendl; + return; + } + mStats[mNumStats] = statp; mColors[mNumStats] = color; mLabels[mNumStats] = label; diff --git a/linden/indra/newview/llgesturemgr.cpp b/linden/indra/newview/llgesturemgr.cpp index c94e9e2..bf3c057 100644 --- a/linden/indra/newview/llgesturemgr.cpp +++ b/linden/indra/newview/llgesturemgr.cpp @@ -103,7 +103,7 @@ void LLGestureManager::activateGesture(const LLUUID& item_id) mDeactivateSimilarNames.clear(); const BOOL inform_server = TRUE; - const BOOL deactivate_similar = TRUE; + const BOOL deactivate_similar = FALSE; activateGestureWithAsset(item_id, asset_id, inform_server, deactivate_similar); } @@ -206,6 +206,11 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id, BOOL inform_server, BOOL deactivate_similar) { + if( !gAssetStorage ) + { + llwarns << "LLGestureManager::activateGestureWithAsset without valid gAssetStorage" << llendl; + return; + } // If gesture is already active, nothing to do. if (isGestureActive(item_id)) { @@ -418,7 +423,7 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new LLLoadInfo* info = new LLLoadInfo; info->mItemID = item_id; info->mInformServer = TRUE; - info->mDeactivateSimilar = TRUE; + info->mDeactivateSimilar = FALSE; const BOOL high_priority = TRUE; gAssetStorage->getAssetData(asset_id, @@ -489,6 +494,8 @@ BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::s LLString cur_token_lower = cur_token; LLString::toLower(cur_token_lower); + // collect gestures that match + std::vector matching; item_map_t::iterator it; for (it = mActive.begin(); it != mActive.end(); ++it) { @@ -496,16 +503,32 @@ BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::s // Gesture asset data might not have arrived yet if (!gesture) continue; - + if (!stricmp(gesture->mTrigger.c_str(), cur_token_lower.c_str())) { + matching.push_back(gesture); + } + + gesture = NULL; + } + + + if (matching.size() > 0) + { + // choose one at random + { + S32 random = ll_rand(matching.size()); + + gesture = matching[random]; + playGesture(gesture); if (!gesture->mReplaceText.empty()) { if( !first_token ) { - revised_string->append( " " ); + if (revised_string) + revised_string->append( " " ); } // Don't muck with the user's capitalization if we don't have to. @@ -514,30 +537,34 @@ BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::s LLString::toLower(output_lower); if( cur_token_lower == output_lower ) { - revised_string->append( cur_token ); + if (revised_string) + revised_string->append( cur_token ); } else { - revised_string->append( output ); + if (revised_string) + revised_string->append( output ); } } found_gestures = TRUE; - break; } - gesture = NULL; } } - - if( !gesture ) + + if(!gesture) { + // This token doesn't match a gesture. Pass it through to the output. if( !first_token ) { - revised_string->append( " " ); + if (revised_string) + revised_string->append( " " ); } - revised_string->append( cur_token ); + if (revised_string) + revised_string->append( cur_token ); } first_token = FALSE; + gesture = NULL; } return found_gestures; } @@ -545,7 +572,10 @@ BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::s BOOL LLGestureManager::triggerGesture(KEY key, MASK mask) { + std::vector matching; item_map_t::iterator it; + + // collect matching gestures for (it = mActive.begin(); it != mActive.end(); ++it) { LLMultiGesture* gesture = (*it).second; @@ -556,10 +586,20 @@ BOOL LLGestureManager::triggerGesture(KEY key, MASK mask) if (gesture->mKey == key && gesture->mMask == mask) { - playGesture(gesture); - return TRUE; + matching.push_back(gesture); } } + + // choose one and play it + if (matching.size() > 0) + { + U32 random = ll_rand(matching.size()); + + LLMultiGesture* gesture = matching[random]; + + playGesture(gesture); + return TRUE; + } return FALSE; } diff --git a/linden/indra/newview/llgesturemgr.h b/linden/indra/newview/llgesturemgr.h index 8544599..29aecf3 100644 --- a/linden/indra/newview/llgesturemgr.h +++ b/linden/indra/newview/llgesturemgr.h @@ -105,7 +105,7 @@ public: BOOL triggerGesture(KEY key, MASK mask); // Trigger all gestures referenced as substrings in this string - BOOL triggerAndReviseString(const std::string &str, std::string *revised_string); + BOOL triggerAndReviseString(const std::string &str, std::string *revised_string = NULL); // Does some gesture have this key bound? BOOL isKeyBound(KEY key, MASK mask); diff --git a/linden/indra/newview/llglslshader.cpp b/linden/indra/newview/llglslshader.cpp index 9c3d707..cc440c4 100644 --- a/linden/indra/newview/llglslshader.cpp +++ b/linden/indra/newview/llglslshader.cpp @@ -180,7 +180,7 @@ static LLString get_object_log(GLhandleARB ret) //the log could be any size, so allocate appropriately GLcharARB* log = new GLcharARB[length]; glGetInfoLogARB(ret, length, &length, log); - res = LLString(log); + res = LLString((char *)log); delete[] log; } return res; @@ -249,11 +249,12 @@ GLhandleARB LLShaderMgr::loadShader(const LLString& filename, S32 cls, GLenum ty GLcharARB* text[1024]; GLuint count = 0; + //copy file into memory - while(fgets(buff, 1024, file) != NULL) + while(fgets((char *)buff, 1024, file) != NULL && count < (sizeof(buff)/sizeof(buff[0]))) { - text[count++] = strdup(buff); - } + text[count++] = (GLcharARB *)strdup((char *)buff); + } fclose(file); //create shader object @@ -1036,7 +1037,7 @@ BOOL LLGLSLShader::mapAttributes(const char** attrib_names, S32 count) for (S32 i = 0; i < (S32) LLShaderMgr::sReservedAttribCount; i++) { const char* name = LLShaderMgr::sReservedAttribs[i]; - S32 index = glGetAttribLocationARB(mProgramObject, name); + S32 index = glGetAttribLocationARB(mProgramObject, (GLcharARB *)name); if (index != -1) { mAttribute[i] = index; @@ -1047,7 +1048,7 @@ BOOL LLGLSLShader::mapAttributes(const char** attrib_names, S32 count) for (S32 i = 0; i < count; i++) { const char* name = attrib_names[i]; - S32 index = glGetAttribLocationARB(mProgramObject, name); + S32 index = glGetAttribLocationARB(mProgramObject, (GLcharARB *)name); if (index != -1) { mAttribute[LLShaderMgr::sReservedAttribCount + i] = index; @@ -1074,7 +1075,7 @@ void LLGLSLShader::mapUniform(GLint index, const char** uniform_names, S32 count char name[1024]; /* Flawfinder: ignore */ name[0] = 0; - glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, name); + glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name); //find the index of this uniform for (S32 i = 0; i < (S32) LLShaderMgr::sReservedUniformCount; i++) @@ -1082,7 +1083,7 @@ void LLGLSLShader::mapUniform(GLint index, const char** uniform_names, S32 count if (mUniform[i] == -1 && !strncmp(LLShaderMgr::sReservedUniforms[i],name, strlen(LLShaderMgr::sReservedUniforms[i]))) /* Flawfinder: ignore */ { //found it - S32 location = glGetUniformLocationARB(mProgramObject, name); + S32 location = glGetUniformLocationARB(mProgramObject, (GLcharARB *)name); mUniform[i] = location; llinfos << "Uniform " << name << " is at location " << location << llendl; mTexture[i] = mapUniformTextureChannel(location, type); @@ -1096,7 +1097,7 @@ void LLGLSLShader::mapUniform(GLint index, const char** uniform_names, S32 count !strncmp(uniform_names[i],name, strlen(uniform_names[i]))) /* Flawfinder: ignore */ { //found it - S32 location = glGetUniformLocationARB(mProgramObject, name); + S32 location = glGetUniformLocationARB(mProgramObject, (GLcharARB *)name); mUniform[i+LLShaderMgr::sReservedUniformCount] = location; llinfos << "Uniform " << name << " is at location " << location << " stored in index " << (i+LLShaderMgr::sReservedUniformCount) << llendl; @@ -1215,7 +1216,7 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) void LLScatterShader::init(GLhandleARB shader, int map_stage) { glUseProgramObjectARB(shader); - glUniform1iARB(glGetUniformLocationARB(shader, "scatterMap"), map_stage); + glUniform1iARB(glGetUniformLocationARB(shader, (GLcharARB *)"scatterMap"), map_stage); glUseProgramObjectARB(0); } diff --git a/linden/indra/newview/llhoverview.cpp b/linden/indra/newview/llhoverview.cpp index d00b062..f9c3443 100644 --- a/linden/indra/newview/llhoverview.cpp +++ b/linden/indra/newview/llhoverview.cpp @@ -224,6 +224,13 @@ void LLHoverView::updateText() mText.deleteAllData(); if ( hit_object ) { + if ( hit_object->isHUDAttachment() ) + { + // no hover tips for HUD elements, since they can obscure + // what the HUD is displaying + return; + } + if ( hit_object->isAttachment() ) { // get root of attachment then parent, which is avatar diff --git a/linden/indra/newview/llhudeffectlookat.cpp b/linden/indra/newview/llhudeffectlookat.cpp index 813f924..da0ec60 100644 --- a/linden/indra/newview/llhudeffectlookat.cpp +++ b/linden/indra/newview/llhudeffectlookat.cpp @@ -442,12 +442,25 @@ void LLHUDEffectLookAt::update() } } +/** + * Initializes the mTargetPos member from the current mSourceObjec and mTargetObject + * (and possibly mTargetOffsetGlobal). + * When mTargetObject is another avatar, it sets mTargetPos to be their eyes. + * + * Has the side-effect of also calling setAnimationData("LookAtPoint") with the new + * mTargetPos on the source object which is assumed to be an avatar. + */ void LLHUDEffectLookAt::calcTargetPosition() { - LLViewerObject *targetObject = (LLViewerObject *)mTargetObject; + if (gNoRender) + { + return; + } + + LLViewerObject *target_obj = (LLViewerObject *)mTargetObject; LLVector3 local_offset; - if (targetObject) + if (target_obj) { local_offset.setVec(mTargetOffsetGlobal); } @@ -456,20 +469,16 @@ void LLHUDEffectLookAt::calcTargetPosition() local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal); } - if (gNoRender) - { - return; - } - LLVector3 head_position = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->mHeadp->getWorldPosition(); + LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; - if (targetObject && targetObject->mDrawable.notNull()) + if (target_obj && target_obj->mDrawable.notNull()) { - LLQuaternion objRot; - if (targetObject->isAvatar()) + LLQuaternion target_rot; + if (target_obj->isAvatar()) { - LLVOAvatar *avatarp = (LLVOAvatar *)targetObject; + LLVOAvatar *target_av = (LLVOAvatar *)target_obj; - BOOL looking_at_self = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->isSelf() && avatarp->isSelf(); + BOOL looking_at_self = source_avatar->isSelf() && target_av->isSelf(); // if selecting self, stare forward if (looking_at_self && mTargetOffsetGlobal.magVecSquared() < MIN_TARGET_OFFSET_SQUARED) @@ -479,46 +488,46 @@ void LLHUDEffectLookAt::calcTargetPosition() local_offset.setVec(mTargetOffsetGlobal); } - mTargetPos = avatarp->mHeadp->getWorldPosition(); + // look the other avatar in the eye. note: what happens if target is self? -MG + mTargetPos = target_av->mHeadp->getWorldPosition(); if (mTargetType == LOOKAT_TARGET_MOUSELOOK || mTargetType == LOOKAT_TARGET_FREELOOK) { // mouselook and freelook target offsets are absolute - objRot = LLQuaternion::DEFAULT; + target_rot = LLQuaternion::DEFAULT; } else if (looking_at_self && gAgent.cameraCustomizeAvatar()) { // *NOTE: We have to do this because animation // overrides do not set lookat behavior. // *TODO: animation overrides for lookat behavior. - objRot = avatarp->mPelvisp->getWorldRotation(); + target_rot = target_av->mPelvisp->getWorldRotation(); } else { - objRot = avatarp->mRoot.getWorldRotation(); + target_rot = target_av->mRoot.getWorldRotation(); } } - else + else // target obj is not an avatar { - if (targetObject->mDrawable->getGeneration() == -1) + if (target_obj->mDrawable->getGeneration() == -1) { - mTargetPos = targetObject->getPositionAgent(); - objRot = targetObject->getWorldRotation(); + mTargetPos = target_obj->getPositionAgent(); + target_rot = target_obj->getWorldRotation(); } else { - mTargetPos = targetObject->getRenderPosition(); - objRot = targetObject->getRenderRotation(); + mTargetPos = target_obj->getRenderPosition(); + target_rot = target_obj->getRenderRotation(); } } - mTargetPos += (local_offset * objRot); + mTargetPos += (local_offset * target_rot); } - else + else // no target obj or it's not drawable { mTargetPos = local_offset; } - mTargetPos -= head_position; - - ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->setAnimationData("LookAtPoint", (void *)&mTargetPos); + mTargetPos -= source_avatar->mHeadp->getWorldPosition(); + source_avatar->setAnimationData("LookAtPoint", (void *)&mTargetPos); } diff --git a/linden/indra/newview/llhudmanager.cpp b/linden/indra/newview/llhudmanager.cpp index f4eeb5b..0da2f8e 100644 --- a/linden/indra/newview/llhudmanager.cpp +++ b/linden/indra/newview/llhudmanager.cpp @@ -50,7 +50,6 @@ LLColor4 LLHUDManager::sChildColor; LLHUDManager::LLHUDManager() { - mShowPhysical = FALSE; LLHUDManager::sParentColor = gColors.getColor("FocusColor"); // rdw commented out since it's not used. Also removed from colors_base.xml @@ -59,110 +58,10 @@ LLHUDManager::LLHUDManager() LLHUDManager::~LLHUDManager() { - mHUDJoints.reset(); - mHUDSelectedJoints.reset(); mHUDEffects.reset(); } -void LLHUDManager::toggleShowPhysical(const BOOL show_physical) -{ - if (show_physical == mShowPhysical) - { - return; - } - - mShowPhysical = show_physical; - if (show_physical) - { - S32 i; - for (i = 0; i < gObjectList.getNumObjects(); i++) - { - LLViewerObject *vobjp = gObjectList.getObject(i); - - if (vobjp && vobjp->isJointChild() && vobjp->getParent()) - { - LLHUDConnector *connectorp = (LLHUDConnector *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_CONNECTOR); - connectorp->setTargets(vobjp, (LLViewerObject *)vobjp->getParent()); - connectorp->setColors(LLColor4(1.f, 1.f, 1.f, 1.f), sChildColor, sParentColor); - EHavokJointType joint_type = vobjp->getJointType(); - if (HJT_HINGE == joint_type) - { - connectorp->setLabel("Hinge"); - } - else if (HJT_POINT == joint_type) - { - connectorp->setLabel("P2P"); - } -#if 0 - else if (HJT_LPOINT == joint_type) - { - connectorp->setLabel("LP2P"); - } -#endif -#if 0 - else if (HJT_WHEEL == joint_type) - { - connectorp->setLabel("Wheel"); - } -#endif - mHUDJoints.put(connectorp); - } - } - } - else - { - mHUDJoints.reset(); - } -} - -void LLHUDManager::showJoints(LLDynamicArray < LLViewerObject* > *object_list) -{ - for (S32 i=0; icount(); i++) - { - LLViewerObject *vobjp = object_list->get(i); - if (vobjp && vobjp->isJointChild() && vobjp->getParent()) - { - LLHUDConnector *connectorp = (LLHUDConnector *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_CONNECTOR); - connectorp->setTargets(vobjp, (LLViewerObject *)vobjp->getParent()); - connectorp->setColors(LLColor4(1.f, 1.f, 1.f, 1.f), sChildColor, sParentColor); - - EHavokJointType joint_type = vobjp->getJointType(); - if (HJT_HINGE == joint_type) - { - connectorp->setLabel("Hinge"); - } - else if (HJT_POINT == joint_type) - { - connectorp->setLabel("P2P"); - } -#if 0 - else if (HJT_LPOINT == joint_type) - { - connectorp->setLabel("LP2P"); - } -#endif -#if 0 - else if (HJT_WHEEL == joint_type) - { - connectorp->setLabel("Wheel"); - } -#endif - mHUDSelectedJoints.put(connectorp); - } - } -} - -void LLHUDManager::clearJoints() -{ - mHUDSelectedJoints.reset(); -} - -BOOL LLHUDManager::getShowPhysical() const -{ - return mShowPhysical; -} - void LLHUDManager::updateEffects() { LLFastTimer ftm(LLFastTimer::FTM_HUD_EFFECTS); diff --git a/linden/indra/newview/llhudmanager.h b/linden/indra/newview/llhudmanager.h index 41cf018..44c8ed5 100644 --- a/linden/indra/newview/llhudmanager.h +++ b/linden/indra/newview/llhudmanager.h @@ -50,11 +50,6 @@ public: LLHUDManager(); ~LLHUDManager(); - void toggleShowPhysical(const BOOL show_physical); - void showJoints(LLDynamicArray < LLViewerObject* > *object_list); - void clearJoints(); - BOOL getShowPhysical() const; - LLHUDEffect *createViewerEffect(const U8 type, BOOL send_to_sim = TRUE, BOOL originated_here = TRUE); void updateEffects(); @@ -67,12 +62,7 @@ public: static LLColor4 sChildColor; protected: - LLDynamicArrayPtr > mHUDJoints; - LLDynamicArrayPtr > mHUDSelectedJoints; LLDynamicArrayPtr > mHUDEffects; - - // ALT held down this frame? - BOOL mShowPhysical; }; extern LLHUDManager *gHUDManager; diff --git a/linden/indra/newview/llhudobject.cpp b/linden/indra/newview/llhudobject.cpp index 6032354..3788c29 100644 --- a/linden/indra/newview/llhudobject.cpp +++ b/linden/indra/newview/llhudobject.cpp @@ -42,6 +42,7 @@ #include "llhudeffectlookat.h" //Ventrella +#include "llvoicevisualizer.h" #include "llanimalcontrols.h" #include "lllocalanimationobject.h" #include "llcape.h" @@ -225,6 +226,9 @@ LLHUDObject *LLHUDObject::addHUDObject(const U8 type) case LL_HUD_EFFECT_LOOKAT: hud_objectp = new LLHUDEffectLookAt(type); break; + case LL_HUD_EFFECT_VOICE_VISUALIZER: + hud_objectp = new LLVoiceVisualizer(type); + break; case LL_HUD_EFFECT_POINTAT: hud_objectp = new LLHUDEffectPointAt(type); break; diff --git a/linden/indra/newview/llhudobject.h b/linden/indra/newview/llhudobject.h index b3af006..a64fe9b 100644 --- a/linden/indra/newview/llhudobject.h +++ b/linden/indra/newview/llhudobject.h @@ -88,7 +88,8 @@ public: LL_HUD_EFFECT_SPIRAL, LL_HUD_EFFECT_EDIT, LL_HUD_EFFECT_LOOKAT, - LL_HUD_EFFECT_POINTAT + LL_HUD_EFFECT_POINTAT, + LL_HUD_EFFECT_VOICE_VISUALIZER // Ventrella }; protected: static void sortObjects(); diff --git a/linden/indra/newview/llhudtext.cpp b/linden/indra/newview/llhudtext.cpp index fce52f1..20bf486 100644 --- a/linden/indra/newview/llhudtext.cpp +++ b/linden/indra/newview/llhudtext.cpp @@ -859,7 +859,8 @@ void LLHUDText::updateAll() } if (src_textp->mSoftScreenRect.rectInRect(&dst_textp->mSoftScreenRect)) { - LLRectf intersect_rect = src_textp->mSoftScreenRect & dst_textp->mSoftScreenRect; + LLRectf intersect_rect = src_textp->mSoftScreenRect; + intersect_rect.intersectWith(dst_textp->mSoftScreenRect); intersect_rect.stretch(-BUFFER_SIZE * 0.5f); F32 src_center_x = src_textp->mSoftScreenRect.getCenterX(); diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index b74fff0..2529d04 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp @@ -33,7 +33,6 @@ #include "indra_constants.h" #include "llfocusmgr.h" #include "llfontgl.h" -#include "llhttpclient.h" #include "llrect.h" #include "llerror.h" #include "llstring.h" @@ -43,12 +42,14 @@ #include "llagent.h" #include "llbutton.h" #include "llcallingcard.h" +#include "llchat.h" #include "llconsole.h" #include "llfloater.h" #include "llinventory.h" #include "llinventorymodel.h" #include "llinventoryview.h" #include "llfloateravatarinfo.h" +#include "llfloaterchat.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llresmgr.h" @@ -61,8 +62,13 @@ #include "llvieweruictrlfactory.h" #include "lllogchat.h" #include "llfloaterhtml.h" -#include "llviewerregion.h" #include "llweb.h" +#include "llhttpclient.h" +#include "llfloateractivespeakers.h" // LLSpeakerMgr +#include "llfloatergroupinfo.h" +#include "llsdutil.h" +#include "llnotify.h" +#include "llmutelist.h" // // Constants @@ -79,6 +85,10 @@ static LLString sTitleString = "Instant Message with [NAME]"; static LLString sTypingStartString = "[NAME]: ..."; static LLString 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; + void session_starter_helper(const LLUUID& temp_session_id, const LLUUID& other_participant_id, EInstantMessage im_type) @@ -161,45 +171,669 @@ bool send_start_session_messages(const LLUUID& temp_session_id, return false; } -// Member Functions +class LLVoiceCallCapResponder : public LLHTTPClient::Responder +{ +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); + +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) + { + 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 LLString& 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()->addStatusObserver(this); +} + +LLVoiceChannel::~LLVoiceChannel() +{ + // CANNOT do this here, since it will crash on quit in the LLVoiceChannelProximal singleton destructor. + // Do it in all other subclass destructors instead. + // deactivate(); + + // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed. + if(gVoiceClient) + { + gVoiceClient->removeStatusObserver(this); + } + + sVoiceChannelMap.erase(mSessionID); + sVoiceChannelURIMap.erase(mURI); +} + +void LLVoiceChannel::setChannelInfo( + const LLString& uri, + const LLString& 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(); + } + } +} + +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(); + break; + case STATUS_LOGGED_IN: + if (!mLoginNotificationHandle.isDead()) + { + LLNotifyBox* notifyp = (LLNotifyBox*)LLPanel::getPanelByHandle(mLoginNotificationHandle); + if (notifyp) + { + notifyp->close(); + } + mLoginNotificationHandle.markDead(); + } + break; + case STATUS_LEFT_CHANNEL: + if (callStarted() && !mIgnoreNextSessionLeave) + { + // if forceably removed from channel + // update the UI and revert to default channel + LLNotifyBox::showXml("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); + } + 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) + { + if (sCurrentVoiceChannel) + { + sCurrentVoiceChannel->deactivate(); + } + sCurrentVoiceChannel = this; + } + + 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(LLString 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(LLString 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(); +} + +// +// LLVoiceChannelGroup +// + +LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const LLString& session_name) : + LLVoiceChannel(session_id, session_name) +{ +} + +LLVoiceChannelGroup::~LLVoiceChannelGroup() +{ + deactivate(); +} + +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::handleError(EStatusType status) +{ + std::string notify; + switch(status) + { + case ERROR_CHANNEL_LOCKED: + case ERROR_CHANNEL_FULL: + notify = "VoiceChannelFull"; + break; + case ERROR_UNKNOWN: + break; + default: + break; + } + + // notification + if (!notify.empty()) + { + LLNotifyBox::showXml(notify, mNotifyArgs); + // echo to im window + gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, LLNotifyBox::getTemplateMessage(notify, mNotifyArgs).c_str()); + } + + LLVoiceChannel::handleError(status); +} + +// +// LLVoiceChannelProximal +// +LLVoiceChannelProximal::LLVoiceChannelProximal() : + LLVoiceChannel(LLUUID::null, LLString::null) +{ + activate(); +} + +LLVoiceChannelProximal::~LLVoiceChannelProximal() +{ + // DO NOT call deactivate() here, since this will only happen at atexit() time. +} + +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; + 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()) + { + LLNotifyBox::showXml(notify, mNotifyArgs); + } + + LLVoiceChannel::handleError(status); +} + +void LLVoiceChannelProximal::deactivate() +{ + if (callStarted()) + { + setState(STATE_HUNG_UP); + } +} + // +// LLVoiceChannelP2P +// +LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const LLString& session_name, const LLUUID& other_user_id) : + LLVoiceChannelGroup(session_id, session_name), + mOtherUserID(other_user_id) +{ + // make sure URI reflects encoded version of other user's agent id + setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id)); +} + +LLVoiceChannelP2P::~LLVoiceChannelP2P() +{ + deactivate(); +} + +void LLVoiceChannelP2P::handleStatusChange(EStatusType type) +{ + // status updates + switch(type) + { + case STATUS_LEFT_CHANNEL: + if (callStarted() && !mIgnoreNextSessionLeave) + { + if (mState == STATE_RINGING) + { + // other user declined call + LLNotifyBox::showXml("P2PCallDeclined", mNotifyArgs); + } + else + { + // other user hung up + LLNotifyBox::showXml("VoiceChannelDisconnectedP2P", mNotifyArgs); + } + deactivate(); + } + mIgnoreNextSessionLeave = FALSE; + return; + default: + break; + } + + LLVoiceChannelGroup::handleStatusChange(type); +} + +void LLVoiceChannelP2P::handleError(EStatusType type) +{ + switch(type) + { + case ERROR_NOT_AVAILABLE: + LLNotifyBox::showXml("P2PCallNoAnswer", mNotifyArgs); + break; + default: + break; + } + + LLVoiceChannelGroup::handleError(type); +} + +void LLVoiceChannelP2P::activate() +{ + if (callStarted()) return; -LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, - const LLRect& rect, - const std::string& session_label, - const LLUUID& session_id, - const LLUUID& other_participant_id, - EInstantMessage dialog) : + LLVoiceChannel::activate(); + + if (callStarted()) + { + // no session handle yet, we're starting the call + if (mSessionHandle.empty()) + { + LLVoiceClient::getInstance()->callUser(mOtherUserID); + } + // otherwise answering the call + else + { + LLVoiceClient::getInstance()->answerInvite(mSessionHandle, mOtherUserID); + // 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 LLString& handle) +{ + 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. + setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID)); + + if (needs_activate) + { + activate(); + } +} + +// +// LLFloaterIMPanel +// +LLFloaterIMPanel::LLFloaterIMPanel( + const std::string& name, + const LLRect& rect, + const std::string& session_label, + const LLUUID& session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog) : LLFloater(name, rect, session_label), mInputEditor(NULL), mHistoryEditor(NULL), mSessionUUID(session_id), - mSessionInitRequested(FALSE), + mVoiceChannel(NULL), mSessionInitialized(FALSE), + mOtherParticipantUUID(other_participant_id), mDialog(dialog), mTyping(FALSE), mOtherTyping(FALSE), mTypingLineStartIndex(0), mSentTypingState(TRUE), + mShowSpeakersOnConnect(TRUE), + mAutoConnect(FALSE), + mSpeakerPanel(NULL), mFirstKeystrokeTimer(), mLastKeystrokeTimer() { init(session_label); } -LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, - const LLRect& rect, - const std::string& session_label, - const LLUUID& session_id, - const LLUUID& other_participant_id, - const LLDynamicArray& ids, - EInstantMessage dialog) : +LLFloaterIMPanel::LLFloaterIMPanel( + const std::string& name, + const LLRect& rect, + const std::string& session_label, + const LLUUID& session_id, + const LLUUID& other_participant_id, + const LLDynamicArray& ids, + EInstantMessage dialog) : LLFloater(name, rect, session_label), mInputEditor(NULL), mHistoryEditor(NULL), mSessionUUID(session_id), - mSessionInitRequested(FALSE), + mVoiceChannel(NULL), mSessionInitialized(FALSE), mOtherParticipantUUID(other_participant_id), mDialog(dialog), @@ -207,6 +841,10 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, mOtherTyping(FALSE), mTypingLineStartIndex(0), mSentTypingState(TRUE), + mShowSpeakersOnConnect(TRUE), + mAutoConnect(FALSE), + mSpeakers(NULL), + mSpeakerPanel(NULL), mFirstKeystrokeTimer(), mLastKeystrokeTimer() { @@ -217,11 +855,53 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& name, void LLFloaterIMPanel::init(const LLString& session_label) { + LLString xml_filename; + switch(mDialog) + { + case IM_SESSION_GROUP_START: + mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); + xml_filename = "floater_instant_message_group.xml"; + mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label); + break; + case IM_SESSION_INVITE: + mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); + if (gAgent.isInGroup(mSessionUUID)) + { + xml_filename = "floater_instant_message_group.xml"; + } + else // must be invite to ad hoc IM + { + xml_filename = "floater_instant_message_ad_hoc.xml"; + } + mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label); + break; + case IM_SESSION_P2P_INVITE: + xml_filename = "floater_instant_message.xml"; + mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, session_label, mOtherParticipantUUID); + break; + case IM_SESSION_CONFERENCE_START: + mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); + xml_filename = "floater_instant_message_ad_hoc.xml"; + mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, session_label); + break; + // just received text from another user + case IM_NOTHING_SPECIAL: + xml_filename = "floater_instant_message.xml"; + mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, session_label, mOtherParticipantUUID); + break; + default: + llwarns << "Unknown session type" << llendl; + xml_filename = "floater_instant_message.xml"; + break; + } + + mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + gUICtrlFactory->buildFloater(this, - "floater_instant_message.xml", - NULL, - FALSE); - + xml_filename, + &getFactoryMap(), + FALSE); + setLabel(session_label); setTitle(session_label); mInputEditor->setMaxTextLength(1023); @@ -256,21 +936,32 @@ void LLFloaterIMPanel::init(const LLString& session_label) mSessionStartMsgPos = mHistoryEditor->getText().length(); - bool log_to_file = false; addHistoryLine( session_start, - LLColor4::grey, - log_to_file); + gSavedSettings.getColor4("SystemChatColor"), + false); } } } +LLFloaterIMPanel::~LLFloaterIMPanel() +{ + delete mSpeakers; + mSpeakers = NULL; + + //kicks you out of the voice channel if it is currently active + + // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point). + mVoiceChannel->deactivate(); + + delete mVoiceChannel; + mVoiceChannel = NULL; +} + BOOL LLFloaterIMPanel::postBuild() { requires("chat_editor", WIDGET_TYPE_LINE_EDITOR); - requires("profile_btn", WIDGET_TYPE_BUTTON); - requires("close_btn", WIDGET_TYPE_BUTTON); requires("im_history", WIDGET_TYPE_TEXT_EDITOR); requires("live_help_dialog", WIDGET_TYPE_TEXT_BOX); requires("title_string", WIDGET_TYPE_TEXT_BOX); @@ -283,22 +974,28 @@ BOOL LLFloaterIMPanel::postBuild() mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived ); mInputEditor->setFocusLostCallback( onInputEditorFocusLost ); mInputEditor->setKeystrokeCallback( onInputEditorKeystroke ); + mInputEditor->setCommitCallback( onCommitChat ); mInputEditor->setCallbackUserData(this); mInputEditor->setCommitOnFocusLost( FALSE ); mInputEditor->setRevertOnEsc( FALSE ); - LLButton* profile_btn = LLUICtrlFactory::getButtonByName(this, "profile_btn"); - profile_btn->setClickedCallback(&LLFloaterIMPanel::onClickProfile, this); + childSetAction("profile_callee_btn", onClickProfile, this); + childSetAction("group_info_btn", onClickGroupInfo, this); + + childSetAction("start_call_btn", onClickStartCall, this); + childSetAction("end_call_btn", onClickEndCall, this); + childSetAction("send_btn", onClickSend, this); + childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this); - LLButton* close_btn = LLUICtrlFactory::getButtonByName(this, "close_btn"); - close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); + //LLButton* close_btn = LLUICtrlFactory::getButtonByName(this, "close_btn"); + //close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this); mHistoryEditor = LLViewerUICtrlFactory::getViewerTextEditorByName(this, "im_history"); mHistoryEditor->setParseHTML(TRUE); - if (IM_SESSION_GROUP_START == mDialog) + if ( IM_SESSION_GROUP_START == mDialog ) { - profile_btn->setEnabled(FALSE); + childSetEnabled("profile_btn", FALSE); } LLTextBox* title = LLUICtrlFactory::getTextBoxByName(this, "title_string"); sTitleString = title->getText(); @@ -311,16 +1008,91 @@ BOOL LLFloaterIMPanel::postBuild() this, "session_start_string"); sSessionStartString = session_start->getText(); + if (mSpeakerPanel) + { + mSpeakerPanel->refreshSpeakers(); + } + if (mDialog == IM_NOTHING_SPECIAL) + { + childSetCommitCallback("mute_btn", onClickMuteVoice, this); + childSetCommitCallback("speaker_volume", onVolumeChange, this); + } + + setDefaultBtn("send_btn"); return TRUE; } return FALSE; } +void* LLFloaterIMPanel::createSpeakersPanel(void* data) +{ + LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)data; + floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(floaterp->mSpeakers, TRUE); + return floaterp->mSpeakerPanel; +} + +//static +void LLFloaterIMPanel::onClickMuteVoice(LLUICtrl* source, void* user_data) +{ + LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)user_data; + if (floaterp) + { + BOOL is_muted = gMuteListp->isMuted(floaterp->mOtherParticipantUUID, LLMute::flagVoiceChat); + + LLMute mute(floaterp->mOtherParticipantUUID, floaterp->getTitle(), LLMute::AGENT); + if (!is_muted) + { + gMuteListp->add(mute, LLMute::flagVoiceChat); + } + else + { + gMuteListp->remove(mute, LLMute::flagVoiceChat); + } + } +} + +//static +void LLFloaterIMPanel::onVolumeChange(LLUICtrl* source, void* user_data) +{ + LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)user_data; + if (floaterp) + { + gVoiceClient->setUserVolume(floaterp->mOtherParticipantUUID, (F32)source->getValue().asReal()); + } +} + + // virtual void LLFloaterIMPanel::draw() -{ +{ + LLViewerRegion* region = gAgent.getRegion(); + + BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "") + && mSessionInitialized + && LLVoiceClient::voiceEnabled(); + + // hide/show start call and end call buttons + childSetVisible("end_call_btn", mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); + childSetVisible("start_call_btn", mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); + childSetEnabled("start_call_btn", enable_connect); + childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty()); + + if (mAutoConnect && enable_connect) + { + onClickStartCall(this); + mAutoConnect = FALSE; + } + + // show speakers window when voice first connects + if (mShowSpeakersOnConnect && mVoiceChannel->isActive()) + { + childSetVisible("active_speakers_panel", TRUE); + mShowSpeakersOnConnect = FALSE; + } + childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel")); + if (mTyping) { // Time out if user hasn't typed for a while. @@ -339,6 +1111,19 @@ void LLFloaterIMPanel::draw() } } + if (mSpeakerPanel) + { + mSpeakerPanel->refreshSpeakers(); + } + else + { + // refresh volume and mute checkbox + childSetEnabled("speaker_volume", mVoiceChannel->isActive()); + childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID)); + + childSetValue("mute_btn", gMuteListp->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat)); + childSetEnabled("mute_btn", mVoiceChannel->isActive()); + } LLFloater::draw(); } @@ -363,16 +1148,22 @@ private: BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray& ids) { + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + { + return FALSE; + } + S32 count = ids.count(); - if( isAddAllowed() && (count > 0) ) + if( isInviteAllowed() && (count > 0) ) { - llinfos << "LLFloaterIMPanel::inviteToSession() - adding participants" << llendl; + llinfos << "LLFloaterIMPanel::inviteToSession() - inviting participants" << llendl; - std::string url = - gAgent.getRegion()->getCapability("ChatSessionRequest"); + std::string url = region->getCapability("ChatSessionRequest"); LLSD data; + data["params"] = LLSD::emptyArray(); for (int i = 0; i < count; i++) { @@ -399,6 +1190,13 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray& ids) return TRUE; } +void LLFloaterIMPanel::addHistoryLine(const LLUUID& source, const std::string &utf8msg, const LLColor4& color, bool log_to_file) +{ + addHistoryLine(utf8msg, color, log_to_file); + mSpeakers->speakerChatted(source); + mSpeakers->setSpeakerTyping(source, FALSE); +} + void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4& color, bool log_to_file) { LLMultiFloater* hostp = getHost(); @@ -412,7 +1210,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 // Now we're adding the actual line of text, so erase the // "Foo is typing..." text segment, and the optional timestamp // if it was present. JC - removeTypingIndicator(); + removeTypingIndicator(NULL); // Actually add the line LLString timestring; @@ -491,7 +1289,7 @@ BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_paren // but not shift-return or control-return if ( !gSavedSettings.getBOOL("PinTalkViewOpen") && !(mask & MASK_CONTROL) && !(mask & MASK_SHIFT) ) { - gIMView->toggle(NULL); + gIMMgr->toggle(NULL); } } else if ( KEY_ESCAPE == key ) @@ -502,7 +1300,7 @@ BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_paren // Close talk panel with escape if( !gSavedSettings.getBOOL("PinTalkViewOpen") ) { - gIMView->toggle(NULL); + gIMMgr->toggle(NULL); } } } @@ -543,7 +1341,7 @@ BOOL LLFloaterIMPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, BOOL LLFloaterIMPanel::dropCallingCard(LLInventoryItem* item, BOOL drop) { - BOOL rv = isAddAllowed(); + BOOL rv = isInviteAllowed(); if(rv && item && item->getCreatorUUID().notNull()) { if(drop) @@ -563,7 +1361,7 @@ BOOL LLFloaterIMPanel::dropCallingCard(LLInventoryItem* item, BOOL drop) BOOL LLFloaterIMPanel::dropCategory(LLInventoryCategory* category, BOOL drop) { - BOOL rv = isAddAllowed(); + BOOL rv = isInviteAllowed(); if(rv && category) { LLInventoryModel::cat_array_t cats; @@ -592,11 +1390,11 @@ BOOL LLFloaterIMPanel::dropCategory(LLInventoryCategory* category, BOOL drop) return rv; } -BOOL LLFloaterIMPanel::isAddAllowed() const +BOOL LLFloaterIMPanel::isInviteAllowed() const { - return ((IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_INVITE) ); + return ( (IM_SESSION_CONFERENCE_START == mDialog) + || (IM_SESSION_INVITE == mDialog) ); } @@ -621,6 +1419,15 @@ void LLFloaterIMPanel::onClickProfile( void* userdata ) } // static +void LLFloaterIMPanel::onClickGroupInfo( void* userdata ) +{ + // Bring up the Profile window + LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; + + LLFloaterGroupInfo::showFromUUID(self->mSessionUUID); +} + +// static void LLFloaterIMPanel::onClickClose( void* userdata ) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; @@ -631,6 +1438,44 @@ void LLFloaterIMPanel::onClickClose( void* userdata ) } // static +void LLFloaterIMPanel::onClickStartCall(void* userdata) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; + + self->mVoiceChannel->activate(); +} + +// static +void LLFloaterIMPanel::onClickEndCall(void* userdata) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; + + self->getVoiceChannel()->deactivate(); +} + +// static +void LLFloaterIMPanel::onClickSend(void* userdata) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata; + self->sendMsg(); +} + +// static +void LLFloaterIMPanel::onClickToggleActiveSpeakers(void* userdata) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata; + + self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel")); +} + +// static +void LLFloaterIMPanel::onCommitChat(LLUICtrl* caller, void* userdata) +{ + LLFloaterIMPanel* self= (LLFloaterIMPanel*) userdata; + self->sendMsg(); +} + +// static void LLFloaterIMPanel::onInputEditorFocusReceived( LLUICtrl* caller, void* userdata ) { LLFloaterIMPanel* self= (LLFloaterIMPanel*) userdata; @@ -681,7 +1526,7 @@ void LLFloaterIMPanel::onClose(bool app_quitting) mSessionUUID); gAgent.sendReliableMessage(); } - gIMView->removeSession(mSessionUUID); + gIMMgr->removeSession(mSessionUUID); destroy(); } @@ -768,11 +1613,22 @@ void LLFloaterIMPanel::sendMsg() history_echo += ": "; } history_echo += utf8_text; - addHistoryLine(history_echo); + + BOOL other_was_typing = mOtherTyping; + + addHistoryLine(gAgent.getID(), history_echo); + + if (other_was_typing) + { + addTypingIndicator(mOtherTypingName); + } + } } else { + //queue up the message to send once the session is + //initialized mQueuedMsgsForInit.append(utf8_text); } @@ -786,15 +1642,31 @@ void LLFloaterIMPanel::sendMsg() mSentTypingState = TRUE; } +void LLFloaterIMPanel::updateSpeakersList(LLSD speaker_updates) +{ + mSpeakers->processSpeakerListUpdate(speaker_updates); +} + +void LLFloaterIMPanel::setSpeakersListFromMap(LLSD speaker_map) +{ + mSpeakers->processSpeakerMap(speaker_map); +} + +void LLFloaterIMPanel::setSpeakersList(LLSD speaker_list) +{ + mSpeakers->processSpeakerList(speaker_list); +} + void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) { mSessionUUID = session_id; + mVoiceChannel->updateSessionID(session_id); mSessionInitialized = TRUE; //we assume the history editor hasn't moved at all since //we added the starting session message //so, we count how many characters to remove - S32 chars_to_remove = mHistoryEditor->getText().length() - + S32 chars_to_remove = mHistoryEditor->getText().length() - mSessionStartMsgPos; mHistoryEditor->removeTextFromEnd(chars_to_remove); @@ -804,13 +1676,18 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) iter != mQueuedMsgsForInit.endArray(); ++iter) { - deliver_message(iter->asString(), - mSessionUUID, - mOtherParticipantUUID, - mDialog); + deliver_message( + iter->asString(), + mSessionUUID, + mOtherParticipantUUID, + mDialog); } } +void LLFloaterIMPanel::requestAutoConnect() +{ + mAutoConnect = TRUE; +} void LLFloaterIMPanel::setTyping(BOOL typing) { @@ -827,6 +1704,8 @@ void LLFloaterIMPanel::setTyping(BOOL typing) // Will send typing state after a short delay. mSentTypingState = FALSE; } + + mSpeakers->setSpeakerTyping(gAgent.getID(), TRUE); } else { @@ -836,6 +1715,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing) sendTypingState(FALSE); mSentTypingState = TRUE; } + mSpeakers->setSpeakerTyping(gAgent.getID(), FALSE); } mTyping = typing; @@ -864,35 +1744,40 @@ void LLFloaterIMPanel::sendTypingState(BOOL typing) gAgent.sendReliableMessage(); } - void LLFloaterIMPanel::processIMTyping(const LLIMInfo* im_info, BOOL typing) { if (typing) { // other user started typing - addTypingIndicator(im_info); + addTypingIndicator(im_info->mName); } else { // other user stopped typing - removeTypingIndicator(); + removeTypingIndicator(im_info); } } -void LLFloaterIMPanel::addTypingIndicator(const LLIMInfo* im_info) +void LLFloaterIMPanel::addTypingIndicator(const std::string &name) { - mTypingLineStartIndex = mHistoryEditor->getText().length(); - - LLUIString typing_start = sTypingStartString; - typing_start.setArg("[NAME]", im_info->mName); - bool log_to_file = false; - addHistoryLine(typing_start, LLColor4::grey, log_to_file); - mOtherTyping = TRUE; + // we may have lost a "stop-typing" packet, don't add it twice + if (!mOtherTyping) + { + mTypingLineStartIndex = mHistoryEditor->getText().length(); + LLUIString typing_start = sTypingStartString; + typing_start.setArg("[NAME]", name); + addHistoryLine(typing_start, gSavedSettings.getColor4("SystemChatColor"), false); + mOtherTypingName = name; + mOtherTyping = TRUE; + } + // MBW -- XXX -- merge from release broke this (argument to this function changed from an LLIMInfo to a name) + // Richard will fix. +// mSpeakers->setSpeakerTyping(im_info->mFromID, TRUE); } -void LLFloaterIMPanel::removeTypingIndicator() +void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info) { if (mOtherTyping) { @@ -901,6 +1786,10 @@ void LLFloaterIMPanel::removeTypingIndicator() S32 chars_to_remove = mHistoryEditor->getText().length() - mTypingLineStartIndex; mHistoryEditor->removeTextFromEnd(chars_to_remove); + if (im_info) + { + mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE); + } } } @@ -913,4 +1802,3 @@ void LLFloaterIMPanel::chatFromLogFile(LLString line, void* userdata) self->mHistoryEditor->appendColoredText(line, false, true, LLColor4::grey); } - diff --git a/linden/indra/newview/llimpanel.h b/linden/indra/newview/llimpanel.h index 10d387e..525f868 100644 --- a/linden/indra/newview/llimpanel.h +++ b/linden/indra/newview/llimpanel.h @@ -33,15 +33,122 @@ #include "lluuid.h" #include "lldarray.h" #include "llinstantmessage.h" +#include "llvoiceclient.h" class LLLineEditor; class LLViewerTextEditor; class LLInventoryItem; class LLInventoryCategory; +class LLIMSpeakerMgr; +class LLPanelActiveSpeakers; + +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 LLString& session_name); + virtual ~LLVoiceChannel(); + + void setChannelInfo(const LLString& uri, const LLString& credentials); + /*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 getChannelInfo(); + virtual BOOL isActive(); + virtual BOOL callStarted(); + EState getState() { return mState; } + + void updateSessionID(const LLUUID& new_session_id); + + static LLVoiceChannel* getChannelByID(const LLUUID& session_id); + static LLVoiceChannel* getChannelByURI(LLString uri); + static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; } + static void initClass(); + +protected: + void setState(EState state); + void setURI(LLString uri); + + LLString mURI; + LLString mCredentials; + LLUUID mSessionID; + EState mState; + LLString mSessionName; + LLString::format_map_t mNotifyArgs; + BOOL mIgnoreNextSessionLeave; + LLViewHandle mLoginNotificationHandle; + + typedef std::map voice_channel_map_t; + static voice_channel_map_t sVoiceChannelMap; + + typedef std::map voice_channel_map_uri_t; + static voice_channel_map_uri_t sVoiceChannelURIMap; + + static LLVoiceChannel* sCurrentVoiceChannel; +}; + +class LLVoiceChannelGroup : public LLVoiceChannel +{ +public: + LLVoiceChannelGroup(const LLUUID& session_id, const LLString& session_name); + virtual ~LLVoiceChannelGroup(); + + /*virtual*/ void handleError(EStatusType status); + /*virtual*/ void activate(); + /*virtual*/ void deactivate(); + /*virtual*/ void getChannelInfo(); +}; + +class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton +{ +public: + LLVoiceChannelProximal(); + virtual ~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 LLString& session_name, const LLUUID& other_user_id); + virtual ~LLVoiceChannelP2P(); + + /*virtual*/ void handleStatusChange(EStatusType status); + /*virtual*/ void handleError(EStatusType status); + /*virtual*/ void activate(); + /*virtual*/ void getChannelInfo(); + + void setSessionHandle(const LLString& handle); + +private: + LLString mSessionHandle; + LLUUID mOtherUserID; +}; class LLFloaterIMPanel : public LLFloater { public: + // The session id is the id of the session this is for. The target // refers to the user (or group) that where this session serves as // the default. For example, if you open a session though a @@ -60,7 +167,7 @@ public: const LLUUID& target_id, const LLDynamicArray& ids, EInstantMessage dialog); - + virtual ~LLFloaterIMPanel(); /*virtual*/ BOOL postBuild(); @@ -73,6 +180,10 @@ public: // Return TRUE if successful, otherwise FALSE. BOOL inviteToSession(const LLDynamicArray& agent_ids); + void addHistoryLine(const LLUUID& source, + const std::string &utf8msg, + const LLColor4& color = LLColor4::white, + bool log_to_file = true); void addHistoryLine(const std::string &utf8msg, const LLColor4& color = LLColor4::white, bool log_to_file = true); @@ -91,15 +202,32 @@ public: static void onInputEditorFocusReceived( LLUICtrl* caller, void* userdata ); static void onInputEditorFocusLost(LLUICtrl* caller, void* userdata); static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); + static void onCommitChat(LLUICtrl* caller, void* userdata); static void onTabClick( void* userdata ); - static void onClickProfile( void* userdata ); // Profile button pressed + static void onClickProfile( void* userdata ); + static void onClickGroupInfo( void* userdata ); static void onClickClose( void* userdata ); + static void onClickStartCall( void* userdata ); + static void onClickEndCall( void* userdata ); + static void onClickSend( void* userdata ); + static void onClickToggleActiveSpeakers( void* userdata ); + static void* createSpeakersPanel(void* data); + + //callbacks for P2P muting and volume control + static void onClickMuteVoice(LLUICtrl* source, void* user_data); + static void onVolumeChange(LLUICtrl* source, void* user_data); const LLUUID& getSessionID() const { return mSessionUUID; } const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; } + void updateSpeakersList(LLSD speaker_updates); + void setSpeakersListFromMap(LLSD speaker_list); + void setSpeakersList(LLSD speaker_list); + LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } EInstantMessage getDialogType() const { return mDialog; } + void requestAutoConnect(); + void sessionInitReplyReceived(const LLUUID& im_session_id); // Handle other participant in the session typing. @@ -118,17 +246,17 @@ private: BOOL dropCategory(LLInventoryCategory* category, BOOL drop); // test if local agent can add agents. - BOOL isAddAllowed() const; + BOOL isInviteAllowed() const; // Called whenever the user starts or stops typing. // Sends the typing state to the other user if necessary. void setTyping(BOOL typing); // Add the "User is typing..." indicator. - void addTypingIndicator(const LLIMInfo* im_info); + void addTypingIndicator(const std::string &name); // Remove the "User is typing..." indicator. - void removeTypingIndicator(); + void removeTypingIndicator(const LLIMInfo* im_info); void sendTypingState(BOOL typing); @@ -145,7 +273,8 @@ private: // 911 ==> Gaurdian_Angel_Group_ID ^ gAgent.getID() LLUUID mSessionUUID; - BOOL mSessionInitRequested; + LLVoiceChannel* mVoiceChannel; + BOOL mSessionInitialized; LLSD mQueuedMsgsForInit; @@ -165,12 +294,22 @@ private: // Is other user currently typing? BOOL mOtherTyping; + // name of other user who is currently typing + std::string mOtherTypingName; + // Where does the "User is typing..." line start? S32 mTypingLineStartIndex; - //Where does the "Starting session..." line start? + // Where does the "Starting session..." line start? S32 mSessionStartMsgPos; - + BOOL mSentTypingState; + + BOOL mShowSpeakersOnConnect; + + BOOL mAutoConnect; + + LLIMSpeakerMgr* mSpeakers; + LLPanelActiveSpeakers* mSpeakerPanel; // Optimization: Don't send "User is typing..." until the // user has actually been typing for a little while. Prevents diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp index 111852d..9df51b9 100644 --- a/linden/indra/newview/llimview.cpp +++ b/linden/indra/newview/llimview.cpp @@ -1,5 +1,5 @@ /** - * @file llimview.cpp + * @file LLIMMgr.cpp * @brief Container for Instant Messaging * * Copyright (c) 2001-2007, Linden Research, Inc. @@ -32,9 +32,9 @@ #include "llfontgl.h" #include "llrect.h" -#include "lldbstrings.h" #include "llerror.h" #include "llbutton.h" +#include "llhttpclient.h" #include "llsdutil.h" #include "llstring.h" #include "linked_lists.h" @@ -46,8 +46,8 @@ #include "llviewerwindow.h" #include "llresmgr.h" #include "llfloaterchat.h" +#include "llfloaterchatterbox.h" #include "llfloaternewim.h" -#include "llhttpclient.h" #include "llhttpnode.h" #include "llimpanel.h" #include "llresizebar.h" @@ -62,40 +62,48 @@ #include "llcallingcard.h" #include "lltoolbar.h" #include "llviewermessage.h" +#include "llnotify.h" #include "llviewerregion.h" +#include "llfirstuse.h" + const EInstantMessage GROUP_DIALOG = IM_SESSION_GROUP_START; const EInstantMessage DEFAULT_DIALOG = IM_NOTHING_SPECIAL; // // Globals // -LLIMView* gIMView = NULL; +LLIMMgr* gIMMgr = NULL; // // Statics // +//*FIXME: make these all either UIStrings or Strings static LLString sOnlyUserMessage; -static LLString sOfflineMessage; +static LLUIString sOfflineMessage; static std::map sEventStringsMap; static std::map sErrorStringsMap; static std::map sForceCloseSessionMap; +static LLUIString sInviteMessage; // // Helper Functions // // returns true if a should appear before b -static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b ) -{ - return (LLString::compareDict( a->mName, b->mName ) < 0); -} +//static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b ) +//{ +// return (LLString::compareDict( a->mName, b->mName ) < 0); +//} // the other_participant_id is either an agent_id, a group_id, or an inventory // folder item_id (collection of calling cards) -static LLUUID compute_session_id(EInstantMessage dialog, - const LLUUID& other_participant_id) + +// static +LLUUID LLIMMgr::computeSessionID( + EInstantMessage dialog, + const LLUUID& other_participant_id) { LLUUID session_id; if (IM_SESSION_GROUP_START == dialog) @@ -107,6 +115,11 @@ static LLUUID compute_session_id(EInstantMessage dialog, { session_id.generate(); } + else if (IM_SESSION_INVITE == dialog) + { + // use provided session id for invites + session_id = other_participant_id; + } else { LLUUID agent_id = gAgent.getID(); @@ -131,88 +144,35 @@ static LLUUID compute_session_id(EInstantMessage dialog, LLFloaterIM::LLFloaterIM() { + // autoresize=false is necessary to avoid resizing of the IM window whenever + // a session is opened or closed (it would otherwise resize the window to match + // the size of the im-sesssion when they were created. This happens in + // LLMultiFloater::resizeToContents() when called through LLMultiFloater::addFloater()) + this->mAutoResize = FALSE; gUICtrlFactory->buildFloater(this, "floater_im.xml"); } BOOL LLFloaterIM::postBuild() { - requires("only_user_message", WIDGET_TYPE_TEXT_BOX); - requires("offline_message", WIDGET_TYPE_TEXT_BOX); - requires("generic_request_error", WIDGET_TYPE_TEXT_BOX); - requires("insufficient_perms_error", WIDGET_TYPE_TEXT_BOX); - requires("generic_request_error", WIDGET_TYPE_TEXT_BOX); - requires("add_session_event", WIDGET_TYPE_TEXT_BOX); - requires("message_session_event", WIDGET_TYPE_TEXT_BOX); - requires("removed_from_group", WIDGET_TYPE_TEXT_BOX); - - if (checkRequirements()) - { - sOnlyUserMessage = childGetText("only_user_message"); - sOfflineMessage = childGetText("offline_message"); - - sErrorStringsMap["generic"] = - childGetText("generic_request_error"); - sErrorStringsMap["unverified"] = - childGetText("insufficient_perms_error"); - sErrorStringsMap["no_user_911"] = - childGetText("user_no_help"); + sOnlyUserMessage = getFormattedUIString("only_user_message"); + sOfflineMessage = getUIString("offline_message"); - sEventStringsMap["add"] = childGetText("add_session_event"); - sEventStringsMap["message"] = - childGetText("message_session_event"); + sErrorStringsMap["generic"] = + getFormattedUIString("generic_request_error"); + sErrorStringsMap["unverified"] = + getFormattedUIString("insufficient_perms_error"); + sErrorStringsMap["no_user_911"] = + getFormattedUIString("user_no_help"); - sForceCloseSessionMap["removed"] = - childGetText("removed_from_group"); + sEventStringsMap["add"] = childGetText("add_session_event"); + sEventStringsMap["message"] = + getFormattedUIString("message_session_event"); - return TRUE; - } - return FALSE; -} - -//// virtual -//BOOL LLFloaterIM::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) -//{ -// BOOL handled = FALSE; -// if (getEnabled() -// && mask == (MASK_CONTROL|MASK_SHIFT)) -// { -// if (key == 'W') -// { -// LLFloater* floater = getActiveFloater(); -// if (floater) -// { -// if (mTabContainer->getTabCount() == 1) -// { -// // trying to close last tab, close -// // entire window. -// close(); -// handled = TRUE; -// } -// } -// } -// } -// return handled || LLMultiFloater::handleKeyHere(key, mask, called_from_parent); -//} + sForceCloseSessionMap["removed"] = + getFormattedUIString("removed_from_group"); -void LLFloaterIM::onClose(bool app_quitting) -{ - if (!app_quitting) - { - gSavedSettings.setBOOL("ShowIM", FALSE); - } - setVisible(FALSE); -} - -//virtual -void LLFloaterIM::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) -{ - // this code is needed to fix the bug where new IMs received will resize the IM floater. - // SL-29075, SL-24556, and others - LLRect parent_rect = getRect(); - S32 dheight = LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT; - LLRect rect(0, parent_rect.getHeight()-dheight, parent_rect.getWidth(), 0); - floaterp->reshape(rect.getWidth(), rect.getHeight(), TRUE); - LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + sInviteMessage = getUIString("invite_message"); + return TRUE; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -224,7 +184,7 @@ void LLFloaterIM::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLT class LLIMViewFriendObserver : public LLFriendObserver { public: - LLIMViewFriendObserver(LLIMView* tv) : mTV(tv) {} + LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {} virtual ~LLIMViewFriendObserver() {} virtual void changed(U32 mask) { @@ -234,7 +194,30 @@ public: } } protected: - LLIMView* mTV; + LLIMMgr* mTV; +}; + + +class LLIMMgr::LLIMSessionInvite +{ +public: + LLIMSessionInvite(const LLUUID& session_id, const LLString& session_name, const LLUUID& caller_id,const LLString& caller_name, EInstantMessage type, const LLString& session_handle, const LLString& notify_box) : + mSessionID(session_id), + mSessionName(session_name), + mCallerID(caller_id), + mCallerName(caller_name), + mType(type), + mSessionHandle(session_handle), + mNotifyBox(notify_box) + {}; + + LLUUID mSessionID; + LLString mSessionName; + LLUUID mCallerID; + LLString mCallerName; + EInstantMessage mType; + LLString mSessionHandle; + LLString mNotifyBox; }; @@ -245,7 +228,7 @@ protected: // This is a helper function to determine what kind of im session // should be used for the given agent. // static -EInstantMessage LLIMView::defaultIMTypeForAgent(const LLUUID& agent_id) +EInstantMessage LLIMMgr::defaultIMTypeForAgent(const LLUUID& agent_id) { EInstantMessage type = IM_NOTHING_SPECIAL; if(is_agent_friend(agent_id)) @@ -259,20 +242,20 @@ EInstantMessage LLIMView::defaultIMTypeForAgent(const LLUUID& agent_id) } // static -//void LLIMView::onPinButton(void*) +//void LLIMMgr::onPinButton(void*) //{ // BOOL state = gSavedSettings.getBOOL( "PinTalkViewOpen" ); // gSavedSettings.setBOOL( "PinTalkViewOpen", !state ); //} // static -void LLIMView::toggle(void*) +void LLIMMgr::toggle(void*) { static BOOL return_to_mouselook = FALSE; // Hide the button and show the floater or vice versa. - llassert( gIMView ); - BOOL old_state = gIMView->getFloaterOpen(); + llassert( gIMMgr ); + BOOL old_state = gIMMgr->getFloaterOpen(); // If we're in mouselook and we triggered the Talk View, we want to talk. if( gAgent.cameraMouselook() && old_state ) @@ -303,53 +286,39 @@ void LLIMView::toggle(void*) return_to_mouselook = FALSE; } - gIMView->setFloaterOpen( new_state ); + gIMMgr->setFloaterOpen( new_state ); } // // Member Functions // -LLIMView::LLIMView(const std::string& name, const LLRect& rect) : - LLView(name, rect, FALSE), +LLIMMgr::LLIMMgr() : mFriendObserver(NULL), mIMReceived(FALSE) { - gIMView = this; mFriendObserver = new LLIMViewFriendObserver(this); LLAvatarTracker::instance().addObserver(mFriendObserver); - mTalkFloater = new LLFloaterIM(); + //*HACK: use floater to initialize string constants from xml file + // then delete it right away + LLFloaterIM* dummy_floater = new LLFloaterIM(); + delete dummy_floater; - // New IM Panel - mNewIMFloater = new LLFloaterNewIM(); - mTalkFloater->addFloater(mNewIMFloater, TRUE); - - // Tabs sometimes overlap resize handle - mTalkFloater->moveResizeHandleToFront(); + mPendingVoiceInvitations = LLSD::emptyMap(); } -LLIMView::~LLIMView() +LLIMMgr::~LLIMMgr() { LLAvatarTracker::instance().removeObserver(mFriendObserver); delete mFriendObserver; // Children all cleaned up by default view destructor. } -EWidgetType LLIMView::getWidgetType() const -{ - return WIDGET_TYPE_TALK_VIEW; -} - -LLString LLIMView::getWidgetTag() const -{ - return LL_TALK_VIEW_TAG; -} - // Add a message to a session. -void LLIMView::addMessage( +void LLIMMgr::addMessage( const LLUUID& session_id, - const LLUUID& other_participant_id, + const LLUUID& target_id, const char* from, const char* msg, const char* session_name, @@ -358,11 +327,30 @@ void LLIMView::addMessage( const LLUUID& region_id, const LLVector3& position) { + LLUUID other_participant_id = target_id; + bool is_from_system = target_id.isNull(); + + // don't process muted IMs + if (gMuteListp->isMuted( + other_participant_id, + LLMute::flagTextChat) && !gMuteListp->isLinden(from)) + { + return; + } + + //not sure why...but if it is from ourselves we set the target_id + //to be NULL + if( other_participant_id == gAgent.getID() ) + { + other_participant_id = LLUUID::null; + } + LLFloaterIMPanel* floater; LLUUID new_session_id = session_id; if (new_session_id.isNull()) { - new_session_id = compute_session_id(dialog, other_participant_id); + //no session ID...compute new one + new_session_id = computeSessionID(dialog, other_participant_id); } floater = findFloaterBySession(new_session_id); if (!floater) @@ -374,20 +362,10 @@ void LLIMView::addMessage( << " by participant " << other_participant_id << llendl; } } - if(floater) - { - floater->addHistoryLine(msg); - } - else - { - //if we have recently requsted to be dropped from a session - //but are still receiving messages from the session, don't make - //a new floater - if ( mSessionsDropRequested.has(session_id.asString()) ) - { - return ; - } + // create IM window as necessary + if(!floater) + { const char* name = from; if(session_name && (strlen(session_name)>1)) { @@ -395,7 +373,12 @@ void LLIMView::addMessage( } - floater = createFloater(new_session_id, other_participant_id, name, dialog, FALSE); + floater = createFloater( + new_session_id, + other_participant_id, + name, + dialog, + FALSE); // When we get a new IM, and if you are a god, display a bit // of information about the source. This is to help liaisons @@ -415,27 +398,41 @@ void LLIMView::addMessage( //<< "*** region_id: " << region_id << std::endl //<< "*** position: " << position << std::endl; - floater->addHistoryLine(bonus_info.str()); + floater->addHistoryLine(bonus_info.str(), gSavedSettings.getColor4("SystemChatColor")); } - floater->addHistoryLine(msg); make_ui_sound("UISndNewIncomingIMSession"); } - if( !mTalkFloater->getVisible() && !floater->getVisible()) + // now add message to floater + if ( is_from_system ) // chat came from system + { + floater->addHistoryLine( + other_participant_id, + msg, + gSavedSettings.getColor4("SystemChatColor")); + } + else + { + floater->addHistoryLine(other_participant_id, msg); + } + + LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance(LLSD()); + + if( !chat_floater->getVisible() && !floater->getVisible()) { //if the IM window is not open and the floater is not visible (i.e. not torn off) - LLFloater* previouslyActiveFloater = mTalkFloater->getActiveFloater(); + LLFloater* previouslyActiveFloater = chat_floater->getActiveFloater(); // select the newly added floater (or the floater with the new line added to it). // it should be there. - mTalkFloater->selectFloater(floater); + chat_floater->selectFloater(floater); //there was a previously unseen IM, make that old tab flashing //it is assumed that the most recently unseen IM tab is the one current selected/active if ( previouslyActiveFloater && getIMReceived() ) { - mTalkFloater->setFloaterFlashing(previouslyActiveFloater, TRUE); + chat_floater->setFloaterFlashing(previouslyActiveFloater, TRUE); } //notify of a new IM @@ -443,37 +440,87 @@ void LLIMView::addMessage( } } -void LLIMView::notifyNewIM() +void LLIMMgr::addSystemMessage(const LLUUID& session_id, const LLString& message_name, const LLString::format_map_t& args) +{ + LLUIString message; + + // null session id means near me (chat history) + if (session_id.isNull()) + { + LLFloaterChat* floaterp = LLFloaterChat::getInstance(); + + message = floaterp->getUIString(message_name); + message.setArgList(args); + + LLChat chat(message); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::getInstance()->addChatHistory(chat); + } + else // going to IM session + { + LLFloaterIMPanel* floaterp = findFloaterBySession(session_id); + if (floaterp) + { + message = floaterp->getUIString(message_name); + message.setArgList(args); + + gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString().c_str()); + } + } +} + +void LLIMMgr::notifyNewIM() { - if(!gIMView->getFloaterOpen()) + if(!gIMMgr->getFloaterOpen()) { mIMReceived = TRUE; } } -BOOL LLIMView::getIMReceived() const +void LLIMMgr::clearNewIMNotification() +{ + mIMReceived = FALSE; +} + +BOOL LLIMMgr::getIMReceived() const { return mIMReceived; } // This method returns TRUE if the local viewer has a session // currently open keyed to the uuid. -BOOL LLIMView::isIMSessionOpen(const LLUUID& uuid) +BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid) { LLFloaterIMPanel* floater = findFloaterBySession(uuid); if(floater) return TRUE; return FALSE; } +LLUUID LLIMMgr::addP2PSession(const std::string& name, + const LLUUID& other_participant_id, + const LLString& voice_session_handle) +{ + LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id); + + LLFloaterIMPanel* floater = findFloaterBySession(session_id); + if(floater) + { + LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel(); + voice_channelp->setSessionHandle(voice_session_handle); + } + + return session_id; +} + // This adds a session to the talk view. The name is the local name of // the session, dialog specifies the type of session. If the session // exists, it is brought forward. Specifying id = NULL results in an // im session to everyone. Returns the uuid of the session. -LLUUID LLIMView::addSession(const std::string& name, +LLUUID LLIMMgr::addSession(const std::string& name, EInstantMessage dialog, const LLUUID& other_participant_id) { - LLUUID session_id = compute_session_id(dialog, other_participant_id); + LLUUID session_id = computeSessionID(dialog, other_participant_id); LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) @@ -489,7 +536,7 @@ LLUUID LLIMView::addSession(const std::string& name, TRUE); noteOfflineUsers(floater, ids); - mTalkFloater->showFloater(floater); + LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); } else { @@ -502,7 +549,7 @@ LLUUID LLIMView::addSession(const std::string& name, // Adds a session using the given session_id. If the session already exists // the dialog type is assumed correct. Returns the uuid of the session. -LLUUID LLIMView::addSession(const std::string& name, +LLUUID LLIMMgr::addSession(const std::string& name, EInstantMessage dialog, const LLUUID& other_participant_id, const LLDynamicArray& ids) @@ -512,7 +559,7 @@ LLUUID LLIMView::addSession(const std::string& name, return LLUUID::null; } - LLUUID session_id = compute_session_id(dialog, + LLUUID session_id = computeSessionID(dialog, other_participant_id); LLFloaterIMPanel* floater = findFloaterBySession(session_id); @@ -531,7 +578,7 @@ LLUUID LLIMView::addSession(const std::string& name, noteOfflineUsers(floater, ids); } - mTalkFloater->showFloater(floater); + LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); //mTabContainer->selectTabPanel(panel); floater->setInputFocus(TRUE); return floater->getSessionID(); @@ -539,134 +586,272 @@ LLUUID LLIMView::addSession(const std::string& name, // This removes the panel referenced by the uuid, and then restores // internal consistency. The internal pointer is not deleted. -void LLIMView::removeSession(const LLUUID& session_id) +void LLIMMgr::removeSession(const LLUUID& session_id) { LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(floater) { mFloaters.erase(floater->getHandle()); - mTalkFloater->removeFloater(floater); + LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); //mTabContainer->removeTabPanel(floater); } - - if ( session_id.notNull() && floater->getDialogType() != IM_NOTHING_SPECIAL ) - { - mSessionsDropRequested[session_id.asString()] = LLSD(); - } } -void LLIMView::refresh() +void LLIMMgr::inviteToSession( + const LLUUID& session_id, + const LLString& session_name, + const LLUUID& caller_id, + const LLString& caller_name, + EInstantMessage type, + const LLString& session_handle) { - S32 old_scroll_pos = mNewIMFloater->getScrollPos(); - mNewIMFloater->clearAllTargets(); + //ignore voice invites from voice-muted residents + if (gMuteListp->isMuted(caller_id)) + { + return; + } - // build a list of groups. - LLLinkedList group_list( group_dictionary_sort ); + LLString notify_box_type; - LLGroupData* group; - S32 count = gAgent.mGroups.count(); - S32 i; - // read/sort groups on the first pass. - for(i = 0; i < count; ++i) + BOOL ad_hoc_invite = FALSE; + if(type == IM_SESSION_P2P_INVITE) { - group = &(gAgent.mGroups.get(i)); - group_list.addDataSorted( group ); + notify_box_type = "VoiceInviteP2P"; } - - // add groups to the floater on the second pass. - for(group = group_list.getFirstData(); - group; - group = group_list.getNextData()) + else if (gAgent.isInGroup(session_id)) + { + notify_box_type = "VoiceInviteGroup"; + } + else { - mNewIMFloater->addGroup(group->mID, (void*)(&GROUP_DIALOG), TRUE, FALSE); + notify_box_type = "VoiceInviteAdHoc"; + ad_hoc_invite = TRUE; } - // build a set of buddies in the current buddy list. - LLCollectAllBuddies collector; - LLAvatarTracker::instance().applyFunctor(collector); - LLCollectAllBuddies::buddy_map_t::iterator it; - LLCollectAllBuddies::buddy_map_t::iterator end; - it = collector.mOnline.begin(); - end = collector.mOnline.end(); - for( ; it != end; ++it) + LLIMSessionInvite* invite = new LLIMSessionInvite( + session_id, + session_name, + caller_id, + caller_name, + type, + session_handle, + notify_box_type); + + LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id); + if (channelp && channelp->callStarted()) { - mNewIMFloater->addAgent((*it).second, (void*)(&DEFAULT_DIALOG), TRUE); + // you have already started a call to the other user, so just accept the invite + inviteUserResponse(0, invite); + return; } - it = collector.mOffline.begin(); - end = collector.mOffline.end(); - for( ; it != end; ++it) + + if (type == IM_SESSION_P2P_INVITE || ad_hoc_invite) { - mNewIMFloater->addAgent((*it).second, (void*)(&DEFAULT_DIALOG), FALSE); + // is the inviter a friend? + if (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL) + { + // if not, and we are ignoring voice invites from non-friends + // then silently decline + if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) + { + // invite not from a friend, so decline + inviteUserResponse(1, invite); + return; + } + } } - mNewIMFloater->setScrollPos( old_scroll_pos ); + if ( !mPendingVoiceInvitations.has(session_id.asString()) ) + { + if (caller_name.empty()) + { + gCacheName->getName(caller_id, onInviteNameLookup, invite); + } + else + { + LLString::format_map_t args; + args["[NAME]"] = caller_name; + args["[GROUP]"] = session_name; + + LLNotifyBox::showXml(notify_box_type, + args, + inviteUserResponse, + (void*)invite); + + } + mPendingVoiceInvitations[session_id.asString()] = LLSD(); + } } -// JC - This used to set console visibility. It doesn't any more. -void LLIMView::setFloaterOpen(BOOL set_open) +//static +void LLIMMgr::onInviteNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* userdata) { - gSavedSettings.setBOOL("ShowIM", set_open); + LLIMSessionInvite* invite = (LLIMSessionInvite*)userdata; - //RN "visible" and "open" are considered synonomous for now - if (set_open) + invite->mCallerName = llformat("%s %s", first, last); + invite->mSessionName = invite->mCallerName; + + LLString::format_map_t args; + args["[NAME]"] = invite->mCallerName; + + LLNotifyBox::showXml(invite->mNotifyBox, + args, + inviteUserResponse, + (void*)invite); +} + +class LLViewerChatterBoxInvitationAcceptResponder : + public LLHTTPClient::Responder +{ +public: + LLViewerChatterBoxInvitationAcceptResponder( + const LLUUID& session_id, + bool is_voice_invitation) { - mTalkFloater->open(); /*Flawfinder: ignore*/ + mSessionID = session_id; + mIsVoiceInvitiation = is_voice_invitation; } - else + + void result(const LLSD& content) { - mTalkFloater->close(); + if ( gIMMgr) + { + LLFloaterIMPanel* floaterp = + gIMMgr->findFloaterBySession(mSessionID); + + if (floaterp) + { + floaterp->setSpeakersList(content["agents"]); + + if ( mIsVoiceInvitiation ) + { + floaterp->requestAutoConnect(); + LLFloaterIMPanel::onClickStartCall(floaterp); + } + } + + if ( mIsVoiceInvitiation ) + { + gIMMgr->clearPendingVoiceInviation(mSessionID); + } + } } - if( set_open ) + void error(U32 statusNum, const std::string& reason) { - // notifyNewIM(); - - // We're showing the IM, so mark view as non-pending - mIMReceived = FALSE; + //throw something back to the viewer here? + if ( gIMMgr && mIsVoiceInvitiation ) + { + gIMMgr->clearPendingVoiceInviation(mSessionID); + } } -} +private: + LLUUID mSessionID; + bool mIsVoiceInvitiation; +}; -BOOL LLIMView::getFloaterOpen() -{ - return mTalkFloater->getVisible(); -} - -void LLIMView::pruneSessions() +//static +void LLIMMgr::inviteUserResponse(S32 option, void* user_data) { - if(mNewIMFloater) + LLIMSessionInvite* invitep = (LLIMSessionInvite*)user_data; + + switch(option) { - BOOL removed = TRUE; - LLFloaterIMPanel* floater = NULL; - while(removed) + case 0: // accept + { + if (invitep->mType == IM_SESSION_P2P_INVITE) + { + // create a normal IM session + invitep->mSessionID = gIMMgr->addP2PSession( + invitep->mSessionName, + invitep->mCallerID, + invitep->mSessionHandle); + + LLFloaterIMPanel* im_floater = + gIMMgr->findFloaterBySession( + invitep->mSessionID); + if (im_floater) + { + im_floater->requestAutoConnect(); + LLFloaterIMPanel::onClickStartCall(im_floater); + } + + gIMMgr->clearPendingVoiceInviation(invitep->mSessionID); + } + else + { + gIMMgr->addSession( + invitep->mSessionName, + invitep->mType, + invitep->mSessionID); + + std::string url = gAgent.getRegion()->getCapability( + "ChatSessionRequest"); + + LLSD data; + data["method"] = "accept invitation"; + data["session-id"] = invitep->mSessionID; + LLHTTPClient::post( + url, + data, + new LLViewerChatterBoxInvitationAcceptResponder( + invitep->mSessionID, + true)); + } + } + break; + case 2: // mute (also implies ignore, so this falls through to the "ignore" case below) + { + // mute the sender of this invite + if (!gMuteListp->isMuted(invitep->mCallerID)) + { + LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT); + gMuteListp->add(mute); + } + } + /* FALLTHROUGH */ + + case 1: // ignore { - removed = FALSE; - std::set::iterator handle_it; - for(handle_it = mFloaters.begin(); - handle_it != mFloaters.end(); - ++handle_it) + if (invitep->mType == IM_SESSION_P2P_INVITE) { - floater = (LLFloaterIMPanel*)LLFloater::getFloaterByHandle(*handle_it); - if(floater && !mNewIMFloater->isUUIDAvailable(floater->getOtherParticipantID())) + if(gVoiceClient) { - // remove this floater - removed = TRUE; - mFloaters.erase(handle_it++); - floater->close(); - break; + gVoiceClient->declineInvite(invitep->mSessionHandle); } } } + break; } + + delete invitep; } +void LLIMMgr::refresh() +{ +} -void LLIMView::disconnectAllSessions() +void LLIMMgr::setFloaterOpen(BOOL set_open) { - if(mNewIMFloater) + if (set_open) { - mNewIMFloater->setEnabled(FALSE); + LLFloaterChatterBox::showInstance(LLSD()); } + else + { + LLFloaterChatterBox::hideInstance(LLSD()); + } +} + + +BOOL LLIMMgr::getFloaterOpen() +{ + return LLFloaterChatterBox::instanceVisible(LLSD()); +} + +void LLIMMgr::disconnectAllSessions() +{ LLFloaterIMPanel* floater = NULL; std::set::iterator handle_it; for(handle_it = mFloaters.begin(); @@ -681,7 +866,7 @@ void LLIMView::disconnectAllSessions() if (floater) { floater->setEnabled(FALSE); - floater->onClose(TRUE); + floater->close(TRUE); } } } @@ -690,7 +875,7 @@ void LLIMView::disconnectAllSessions() // This method returns the im panel corresponding to the uuid // provided. The uuid can either be a session id or an agent // id. Returns NULL if there is no matching panel. -LLFloaterIMPanel* LLIMView::findFloaterBySession(const LLUUID& session_id) +LLFloaterIMPanel* LLIMMgr::findFloaterBySession(const LLUUID& session_id) { LLFloaterIMPanel* rv = NULL; std::set::iterator handle_it; @@ -709,17 +894,25 @@ LLFloaterIMPanel* LLIMView::findFloaterBySession(const LLUUID& session_id) } -BOOL LLIMView::hasSession(const LLUUID& session_id) +BOOL LLIMMgr::hasSession(const LLUUID& session_id) { return (findFloaterBySession(session_id) != NULL); } +void LLIMMgr::clearPendingVoiceInviation(const LLUUID& session_id) +{ + if ( mPendingVoiceInvitations.has(session_id.asString()) ) + { + mPendingVoiceInvitations.erase(session_id.asString()); + } +} + // create a floater and update internal representation for // consistency. Returns the pointer, caller (the class instance since // it is a private method) is not responsible for deleting the // pointer. Add the floater to this but do not select it. -LLFloaterIMPanel* LLIMView::createFloater( +LLFloaterIMPanel* LLIMMgr::createFloater( const LLUUID& session_id, const LLUUID& other_participant_id, const std::string& session_label, @@ -731,7 +924,7 @@ LLFloaterIMPanel* LLIMView::createFloater( llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl; } - llinfos << "LLIMView::createFloater: from " << other_participant_id + llinfos << "LLIMMgr::createFloater: from " << other_participant_id << " in session " << session_id << llendl; LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, LLRect(), @@ -740,12 +933,12 @@ LLFloaterIMPanel* LLIMView::createFloater( other_participant_id, dialog); LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END; - mTalkFloater->addFloater(floater, FALSE, i_pt); + LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt); mFloaters.insert(floater->getHandle()); return floater; } -LLFloaterIMPanel* LLIMView::createFloater( +LLFloaterIMPanel* LLIMMgr::createFloater( const LLUUID& session_id, const LLUUID& other_participant_id, const std::string& session_label, @@ -758,7 +951,7 @@ LLFloaterIMPanel* LLIMView::createFloater( llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl; } - llinfos << "LLIMView::createFloater: from " << other_participant_id + llinfos << "LLIMMgr::createFloater: from " << other_participant_id << " in session " << session_id << llendl; LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, LLRect(), @@ -768,18 +961,18 @@ LLFloaterIMPanel* LLIMView::createFloater( ids, dialog); LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END; - mTalkFloater->addFloater(floater, FALSE, i_pt); + LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt); mFloaters.insert(floater->getHandle()); return floater; } -void LLIMView::noteOfflineUsers(LLFloaterIMPanel* floater, +void LLIMMgr::noteOfflineUsers(LLFloaterIMPanel* floater, const LLDynamicArray& ids) { S32 count = ids.count(); if(count == 0) { - floater->addHistoryLine(sOnlyUserMessage); + floater->addHistoryLine(sOnlyUserMessage, gSavedSettings.getColor4("SystemChatColor")); } else { @@ -796,25 +989,25 @@ void LLIMView::noteOfflineUsers(LLFloaterIMPanel* floater, LLUIString offline = sOfflineMessage; offline.setArg("[FIRST]", first); offline.setArg("[LAST]", last); - floater->addHistoryLine(offline); + floater->addHistoryLine(offline, gSavedSettings.getColor4("SystemChatColor")); } } } } -void LLIMView::processIMTypingStart(const LLIMInfo* im_info) +void LLIMMgr::processIMTypingStart(const LLIMInfo* im_info) { processIMTypingCore(im_info, TRUE); } -void LLIMView::processIMTypingStop(const LLIMInfo* im_info) +void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info) { processIMTypingCore(im_info, FALSE); } -void LLIMView::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) +void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) { - LLUUID session_id = compute_session_id(im_info->mIMType, im_info->mFromID); + LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID); LLFloaterIMPanel* floater = findFloaterBySession(session_id); if (floater) { @@ -822,8 +1015,9 @@ void LLIMView::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) } } -void LLIMView::updateFloaterSessionID(const LLUUID& old_session_id, - const LLUUID& new_session_id) +void LLIMMgr::updateFloaterSessionID( + const LLUUID& old_session_id, + const LLUUID& new_session_id) { LLFloaterIMPanel* floater = findFloaterBySession(old_session_id); if (floater) @@ -832,9 +1026,9 @@ void LLIMView::updateFloaterSessionID(const LLUUID& old_session_id, } } -void LLIMView::onDropRequestReplyReceived(const LLUUID& session_id) -{ - mSessionsDropRequested.erase(session_id.asString()); +LLFloaterChatterBox* LLIMMgr::getFloater() +{ + return LLFloaterChatterBox::getInstance(LLSD()); } void onConfirmForceCloseError(S32 option, void* data) @@ -842,25 +1036,24 @@ void onConfirmForceCloseError(S32 option, void* data) //only 1 option really LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data); - if ( floater ) floater->onClose(FALSE); + if ( floater ) floater->close(FALSE); } -class LLViewerIMSessionStartReply : public LLHTTPNode +class LLViewerChatterBoxSessionStartReply : public LLHTTPNode { public: virtual void describe(Description& desc) const { - desc.shortInfo("Used for receiving a reply to a request to initialize an IM session"); + desc.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session"); desc.postAPI(); desc.input( "{\"client_session_id\": UUID, \"session_id\": UUID, \"success\" boolean, \"reason\": string"); desc.source(__FILE__, __LINE__); } - virtual void post( - ResponsePtr response, - const LLSD& context, - const LLSD& input) const + virtual void post(ResponsePtr response, + const LLSD& context, + const LLSD& input) const { LLSD body; LLUUID temp_session_id; @@ -874,16 +1067,21 @@ public: if ( success ) { session_id = body["session_id"].asUUID(); - gIMView->updateFloaterSessionID( + gIMMgr->updateFloaterSessionID( temp_session_id, session_id); + LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id); + if (floaterp) + { + floaterp->setSpeakersList(body["agents"]); + } } else { //throw an error dialog and close the temp session's //floater LLFloaterIMPanel* floater = - gIMView->findFloaterBySession(temp_session_id); + gIMMgr->findFloaterBySession(temp_session_id); if (floater) { LLString::format_map_t args; @@ -891,22 +1089,22 @@ public: sErrorStringsMap[body["error"].asString()]; args["[RECIPIENT]"] = floater->getTitle(); - gViewerWindow->alertXml( - "IMSessionStartError", - args, - onConfirmForceCloseError, - floater); + gViewerWindow->alertXml("ChatterBoxSessionStartError", + args, + onConfirmForceCloseError, + floater); + } } } }; -class LLViewerIMSessionEventReply : public LLHTTPNode +class LLViewerChatterBoxSessionEventReply : public LLHTTPNode { public: virtual void describe(Description& desc) const { - desc.shortInfo("Used for receiving a reply to a IM session event"); + desc.shortInfo("Used for receiving a reply to a ChatterBox session event"); desc.postAPI(); desc.input( "{\"event\": string, \"reason\": string, \"success\": boolean, \"session_id\": UUID"); @@ -928,7 +1126,7 @@ public: { //throw an error dialog LLFloaterIMPanel* floater = - gIMView->findFloaterBySession(session_id); + gIMMgr->findFloaterBySession(session_id); if (floater) { LLString::format_map_t args; @@ -938,14 +1136,14 @@ public: sEventStringsMap[body["event"].asString()]; args["[RECIPIENT]"] = floater->getTitle(); - gViewerWindow->alertXml("IMSessionEventError", + gViewerWindow->alertXml("ChatterBoxSessionEventError", args); } } } }; -class LLViewerForceCloseIMSession: public LLHTTPNode +class LLViewerForceCloseChatterBoxSession: public LLHTTPNode { public: virtual void post(ResponsePtr response, @@ -959,7 +1157,7 @@ public: reason = input["body"]["reason"].asString(); LLFloaterIMPanel* floater = - gIMView ->findFloaterBySession(session_id); + gIMMgr ->findFloaterBySession(session_id); if ( floater ) { @@ -968,7 +1166,7 @@ public: args["[NAME]"] = floater->getTitle(); args["[REASON]"] = sForceCloseSessionMap[reason]; - gViewerWindow->alertXml("ForceCloseIMSession", + gViewerWindow->alertXml("ForceCloseChatterBoxSession", args, onConfirmForceCloseError, floater); @@ -976,28 +1174,6 @@ public: } }; -class LLViewerIMSessionDropReply : public LLHTTPNode -{ -public: - virtual void post(ResponsePtr response, - const LLSD& context, - const LLSD& input) const - { - LLUUID session_id; - bool success; - - success = input["body"]["success"].asBoolean(); - session_id = input["body"]["session_id"].asUUID(); - - if ( !success ) - { - //throw an error alert? - } - - gIMView->onDropRequestReplyReceived(session_id); - } -}; - class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode { public: @@ -1006,29 +1182,38 @@ public: const LLSD& context, const LLSD& input) const { + LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID()); + if (floaterp) + { + floaterp->updateSpeakersList(input["body"]["updates"]); + } } }; class LLViewerChatterBoxInvitation : public LLHTTPNode { public: + virtual void post( - ResponsePtr responder, + ResponsePtr response, const LLSD& context, const LLSD& input) const { if ( input["body"].has("instantmessage") ) { + LLString capability = input["body"]["capabilities"]["call"].asString(); + LLSD message_params = input["body"]["instantmessage"]["message_params"]; + //do something here to have the IM invite behave + //just like a normal IM //this is just replicated code from process_improved_im //and should really go in it's own function -jwolk if (gNoRender) { return; } - char buffer[DB_IM_MSG_BUF_SIZE * 2]; /* Flawfinder: ignore */ LLChat chat; @@ -1043,7 +1228,11 @@ public: (time_t) message_params["timestamp"].asInteger(); BOOL is_busy = gAgent.getBusy(); - BOOL is_muted = gMuteListp->isMuted(from_id, name); + BOOL is_muted = gMuteListp->isMuted( + from_id, + name.c_str(), + LLMute::flagTextChat); + BOOL is_linden = gMuteListp->isLinden( name.c_str()); char separator_string[3]=": "; /* Flawfinder: ignore */ @@ -1060,7 +1249,8 @@ public: chat.mMuted = is_muted && !is_linden; chat.mFromID = from_id; chat.mFromName = name; - if (!is_linden && is_busy) + + if (!is_linden && (is_busy || is_muted)) { return; } @@ -1088,10 +1278,9 @@ public: BOOL is_this_agent = FALSE; if(from_id == gAgentID) { - from_id = LLUUID::null; is_this_agent = TRUE; } - gIMView->addMessage( + gIMMgr->addMessage( session_id, from_id, name.c_str(), @@ -1113,11 +1302,7 @@ public: chat.mText = buffer; LLFloaterChat::addChat(chat, TRUE, is_this_agent); - //if we succesfully accepted the invitation - //send a message back down - - //TODO - When availble, have this response just be part - //of an automatic response system + //K now we want to accept the invitation std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -1129,28 +1314,46 @@ public: LLHTTPClient::post( url, data, - NULL); + new LLViewerChatterBoxInvitationAcceptResponder( + input["body"]["session_id"], + false)); } } //end if invitation has instant message + else if ( input["body"].has("voice") ) + { + if (gNoRender) + { + return; + } + + if(!LLVoiceClient::voiceEnabled()) + { + // Don't display voice invites unless the user has voice enabled. + return; + } + + gIMMgr->inviteToSession( + input["body"]["session_id"].asUUID(), + input["body"]["session_name"].asString(), + input["body"]["from_id"].asUUID(), + input["body"]["from_name"].asString(), + IM_SESSION_INVITE); + } } }; -LLHTTPRegistration - gHTTPRegistrationMessageImsessionstartreply( +LLHTTPRegistration + gHTTPRegistrationMessageChatterboxsessionstartreply( "/message/ChatterBoxSessionStartReply"); -LLHTTPRegistration - gHTTPRegistrationMessageImsessioneventreply( +LLHTTPRegistration + gHTTPRegistrationMessageChatterboxsessioneventreply( "/message/ChatterBoxSessionEventReply"); -LLHTTPRegistration - gHTTPRegistrationMessageForceCloseImSession( +LLHTTPRegistration + gHTTPRegistrationMessageForceclosechatterboxsession( "/message/ForceCloseChatterBoxSession"); -LLHTTPRegistration - gHTTPRegistrationMessageImSessionDropReply( - "/message/ChatterBoxSessionLeaveReply"); - LLHTTPRegistration gHTTPRegistrationMessageChatterboxsessionagentlistupdates( "/message/ChatterBoxSessionAgentListUpdates"); diff --git a/linden/indra/newview/llimview.h b/linden/indra/newview/llimview.h index c0b0f79..ca3ef5f 100644 --- a/linden/indra/newview/llimview.h +++ b/linden/indra/newview/llimview.h @@ -1,5 +1,5 @@ /** - * @file llimview.h + * @file LLIMMgr.h * @brief Container for Instant Messaging * * Copyright (c) 2001-2007, Linden Research, Inc. @@ -33,31 +33,32 @@ #include "llinstantmessage.h" #include "lluuid.h" -class LLFloaterNewIM; +class LLFloaterChatterBox; class LLUUID; class LLFloaterIMPanel; class LLFriendObserver; class LLFloaterIM; -class LLIMView : public LLView +class LLIMMgr : public LLSingleton { public: - LLIMView(const std::string& name, const LLRect& rect); - ~LLIMView(); - - virtual EWidgetType getWidgetType() const; - virtual LLString getWidgetTag() const; + LLIMMgr(); + virtual ~LLIMMgr(); // Add a message to a session. The session can keyed to sesion id // or agent id. - void addMessage(const LLUUID& session_id, const LLUUID& target_id, - const char* from, const char* msg, + void addMessage(const LLUUID& session_id, + const LLUUID& target_id, + const char* from, + const char* msg, const char* session_name = NULL, EInstantMessage dialog = IM_NOTHING_SPECIAL, U32 parent_estate_id = 0, const LLUUID& region_id = LLUUID::null, const LLVector3& position = LLVector3::zero); + void addSystemMessage(const LLUUID& session_id, const LLString& message_name, const LLString::format_map_t& args); + // This method returns TRUE if the local viewer has a session // currently open keyed to the uuid. The uuid can be keyed by // either session id or agent id. @@ -82,11 +83,23 @@ public: const LLUUID& other_participant_id, const LLDynamicArray& ids); + // Creates a P2P session with the requisite handle for responding to voice calls + LLUUID addP2PSession(const std::string& name, + const LLUUID& other_participant_id, + const LLString& voice_session_handle); + // This removes the panel referenced by the uuid, and then // restores internal consistency. The internal pointer is not // deleted. void removeSession(const LLUUID& session_id); + void inviteToSession(const LLUUID& session_id, + const LLString& session_name, + const LLUUID& caller, + const LLString& caller_name, + EInstantMessage type, + const LLString& session_handle = LLString::null); + //Updates a given session's session IDs. Does not open, //create or do anything new. If the old session doesn't //exist, then nothing happens. @@ -100,6 +113,7 @@ public: void refresh(); void notifyNewIM(); + void clearNewIMNotification(); // IM received that you haven't seen yet BOOL getIMReceived() const; @@ -107,10 +121,7 @@ public: void setFloaterOpen(BOOL open); /*Flawfinder: ignore*/ BOOL getFloaterOpen(); - LLFloaterIM * getFloater() { return mTalkFloater; } - - // close any sessions which are not available in the newimpanel. - void pruneSessions(); + LLFloaterChatterBox* getFloater(); // This method is used to go through all active sessions and // disable all of them. This method is usally called when you are @@ -131,9 +142,13 @@ public: // is no matching panel. LLFloaterIMPanel* findFloaterBySession(const LLUUID& session_id); - void onDropRequestReplyReceived(const LLUUID& session_id); + static LLUUID computeSessionID(EInstantMessage dialog, const LLUUID& other_participant_id); + void clearPendingVoiceInviation(const LLUUID& session_id); + private: + class LLIMSessionInvite; + // create a panel and update internal representation for // consistency. Returns the pointer, caller (the class instance // since it is a private method) is not responsible for deleting @@ -159,9 +174,8 @@ private: void processIMTypingCore(const LLIMInfo* im_info, BOOL typing); -public: - LLFloaterIM* mTalkFloater; - LLFloaterNewIM* mNewIMFloater; + static void inviteUserResponse(S32 option, void* user_data); + static void onInviteNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* userdata); private: std::set mFloaters; @@ -170,7 +184,7 @@ private: // An IM has been received that you haven't seen yet. BOOL mIMReceived; - LLSD mSessionsDropRequested; + LLSD mPendingVoiceInvitations; }; @@ -178,13 +192,10 @@ class LLFloaterIM : public LLMultiFloater { public: LLFloaterIM(); - ///*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); /*virtual*/ BOOL postBuild(); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainerCommon::END); }; // Globals -extern LLIMView *gIMView; +extern LLIMMgr *gIMMgr; #endif // LL_LLIMView_H diff --git a/linden/indra/newview/llinventoryactions.cpp b/linden/indra/newview/llinventoryactions.cpp index af4e16b..c1b85e1 100644 --- a/linden/indra/newview/llinventoryactions.cpp +++ b/linden/indra/newview/llinventoryactions.cpp @@ -563,7 +563,7 @@ class LLBeginIMSession : public inventory_panel_listener_t if(count > 0) { // create the session - gIMView->setFloaterOpen(TRUE); + gIMMgr->setFloaterOpen(TRUE); S32 i; LLAvatarTracker& at = LLAvatarTracker::instance(); @@ -614,7 +614,7 @@ class LLBeginIMSession : public inventory_panel_listener_t } - gIMView->addSession(name, + gIMMgr->addSession(name, type, members[0], members); diff --git a/linden/indra/newview/llinventorybridge.cpp b/linden/indra/newview/llinventorybridge.cpp index 27be9f6..fd7d98e 100644 --- a/linden/indra/newview/llinventorybridge.cpp +++ b/linden/indra/newview/llinventorybridge.cpp @@ -2593,8 +2593,8 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* if (item && (item->getCreatorUUID() != gAgent.getID()) && (!item->getCreatorUUID().isNull())) { - gIMView->setFloaterOpen(TRUE); - gIMView->addSession(item->getName(), IM_NOTHING_SPECIAL, item->getCreatorUUID()); + gIMMgr->setFloaterOpen(TRUE); + gIMMgr->addSession(item->getName(), IM_NOTHING_SPECIAL, item->getCreatorUUID()); } } else if ("lure" == action) @@ -2671,7 +2671,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) BOOL good_card = (item && (LLUUID::null != item->getCreatorUUID()) && (item->getCreatorUUID() != gAgent.getID())); - + BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); items.push_back("Send Instant Message"); items.push_back("Offer Teleport..."); items.push_back("Conference Chat"); @@ -2679,6 +2679,9 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if (!good_card) { disabled_items.push_back("Send Instant Message"); + } + if (!good_card || !user_online) + { disabled_items.push_back("Offer Teleport..."); disabled_items.push_back("Conference Chat"); } diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp index 743b06d..9df8fa4 100644 --- a/linden/indra/newview/llinventorymodel.cpp +++ b/linden/indra/newview/llinventorymodel.cpp @@ -1486,11 +1486,18 @@ bool LLInventoryModel::loadSkeleton( { LLViewerInventoryCategory* cat = categories[i]; cat_set_t::iterator cit = temp_cats.find(cat); + if (cit == temp_cats.end()) + { + continue; // cache corruption?? not sure why this happens -SJB + } LLViewerInventoryCategory* tcat = *cit; // we can safely ignore anything loaded from file, but // not sent down in the skeleton. - if(cit == not_cached) continue; + if(cit == not_cached) + { + continue; + } if(cat->getVersion() != tcat->getVersion()) { // if the cached version does not match the server version, diff --git a/linden/indra/newview/llinventoryview.cpp b/linden/indra/newview/llinventoryview.cpp index 8ac5f21..112c071 100644 --- a/linden/indra/newview/llinventoryview.cpp +++ b/linden/indra/newview/llinventoryview.cpp @@ -502,11 +502,16 @@ void LLInventoryView::init(LLInventoryModel* inventory) // Load the persistent "Recent Items" settings. // Note that the "All Items" settings do not persist. - if(savedFilterState.has(recent_items_panel->getFilter()->getName())) + if(recent_items_panel) { - LLSD recent_items = savedFilterState.get(recent_items_panel->getFilter()->getName()); - recent_items_panel->getFilter()->fromLLSD(recent_items); + if(savedFilterState.has(recent_items_panel->getFilter()->getName())) + { + LLSD recent_items = savedFilterState.get( + recent_items_panel->getFilter()->getName()); + recent_items_panel->getFilter()->fromLLSD(recent_items); + } } + } @@ -516,7 +521,6 @@ void LLInventoryView::init(LLInventoryModel* inventory) mSearchEditor->setSearchCallback(onSearchEdit, this); } - moveResizeHandleToFront(); sActiveViews.put(this); gInventory.addObserver(this); diff --git a/linden/indra/newview/llmediaremotectrl.cpp b/linden/indra/newview/llmediaremotectrl.cpp index 4549c3b..0d524b0 100644 --- a/linden/indra/newview/llmediaremotectrl.cpp +++ b/linden/indra/newview/llmediaremotectrl.cpp @@ -30,179 +30,66 @@ #include "llmediaremotectrl.h" -#include "llui.h" -#include "lltextbox.h" -#include "llbutton.h" -#include "llfocusmgr.h" -#include "llmediaengine.h" -#include "llviewercontrol.h" +#include "lloverlaybar.h" #include "llvieweruictrlfactory.h" +#include "llpanelaudiovolume.h" //////////////////////////////////////////////////////////////////////////////// // // -LLMediaRemoteCtrl:: -LLMediaRemoteCtrl ( const std::string& name, - const std::string& label, - const LLRect& rect, - const std::string& xml_file ) : +LLMediaRemoteCtrl::LLMediaRemoteCtrl ( const LLString& name, + const LLString& label, + const LLRect& rect, + const LLString& xml_file ) : LLPanel ( name, rect, FALSE ) { - setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); - setBackgroundVisible(TRUE); setIsChrome(TRUE); gUICtrlFactory->buildPanel(this, xml_file); - playButton = LLUICtrlFactory::getButtonByName(this, "play_btn"); - stopButton = LLUICtrlFactory::getButtonByName(this, "stop_btn"); - pauseButton = LLUICtrlFactory::getButtonByName(this, "pause_btn"); - - childSetAction("play_btn",onPlayButton,this); - childSetAction("stop_btn",onStopButton,this); - childSetAction("pause_btn",onPauseButton,this); - - mVolumeSlider = LLViewerUICtrlFactory::getVolumeSliderByName(this, "volume_slider"); - - childSetCommitCallback("volume_slider", onCommitVolume, this); - mIsFocusRoot = TRUE; } -//////////////////////////////////////////////////////////////////////////////// -// -// -LLMediaRemoteCtrl:: -~LLMediaRemoteCtrl () +BOOL LLMediaRemoteCtrl::postBuild() { -} + childSetAction("media_play",LLOverlayBar::mediaPlay,this); + childSetAction("media_stop",LLOverlayBar::mediaStop,this); + childSetAction("media_pause",LLOverlayBar::mediaPause,this); -EWidgetType LLMediaRemoteCtrl::getWidgetType() const -{ - return WIDGET_TYPE_MEDIA_REMOTE; -} + childSetAction("music_play",LLOverlayBar::musicPlay,this); + childSetAction("music_stop",LLOverlayBar::musicStop,this); + childSetAction("music_pause",LLOverlayBar::musicPause,this); -LLString LLMediaRemoteCtrl::getWidgetTag() const -{ - return LL_MEDIA_REMOTE_CTRL_TAG; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// -void -LLMediaRemoteCtrl:: -setTransportState ( TransportState transportStateIn, BOOL pauseEnabled ) -{ - transportState = transportStateIn; - - if ( transportState == Play ) - { - playButton->setVisible ( TRUE ); - playButton->setEnabled ( pauseEnabled ); - - pauseButton->setVisible ( FALSE ); - pauseButton->setEnabled ( FALSE ); - - stopButton->setVisible ( TRUE ); - stopButton->setEnabled ( TRUE ); - } - else - if ( transportState == Pause ) - { - playButton->setVisible ( FALSE ); - playButton->setEnabled ( FALSE ); - - pauseButton->setVisible ( TRUE ); - pauseButton->setEnabled ( TRUE ); - - stopButton->setVisible ( TRUE ); - stopButton->setEnabled ( TRUE ); - } - else - if ( transportState == Stop ) - { - playButton->setVisible ( TRUE ); - playButton->setEnabled ( TRUE ); - - pauseButton->setVisible ( FALSE ); - pauseButton->setEnabled ( FALSE ); - - stopButton->setVisible ( TRUE ); - stopButton->setEnabled ( FALSE ); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// -LLMediaRemoteCtrl::TransportState -LLMediaRemoteCtrl:: -getTransportState () -{ - return transportState; -} - - -//////////////////////////////////////////////////////////////////////////////// -// -// -void -LLMediaRemoteCtrl:: -setVolume ( F32 volumeIn ) -{ - mVolumeSlider->setValue ( volumeIn ); + childSetAction("volume",LLOverlayBar::toggleAudioVolumeFloater,this); + + return TRUE; } -//////////////////////////////////////////////////////////////////////////////// -// -// -void -LLMediaRemoteCtrl:: -onCommitVolume ( LLUICtrl* ctrl, void* data ) +LLMediaRemoteCtrl::~LLMediaRemoteCtrl () { - LLMediaRemoteCtrl* self = ( LLMediaRemoteCtrl* ) data; - - LLMediaRemoteCtrlEvent event ( self, (F32)self->mVolumeSlider->getValue().asReal() ); - self->mediaRemoteCtrlEventEmitter.update ( &LLMediaRemoteCtrlObserver::onVolumeChange, event ); } //////////////////////////////////////////////////////////////////////////////// // // -void -LLMediaRemoteCtrl:: -onPlayButton ( void* data ) +EWidgetType LLMediaRemoteCtrl::getWidgetType() const { - LLMediaRemoteCtrl* self = ( LLMediaRemoteCtrl* ) data; - - LLMediaRemoteCtrlEvent event ( self, 0.0f ); - self->mediaRemoteCtrlEventEmitter.update ( &LLMediaRemoteCtrlObserver::onPlayButtonPressed, event ); + return WIDGET_TYPE_MEDIA_REMOTE; } -//////////////////////////////////////////////////////////////////////////////// -// -// -void -LLMediaRemoteCtrl:: -onPauseButton ( void* data ) +LLString LLMediaRemoteCtrl::getWidgetTag() const { - LLMediaRemoteCtrl* self = ( LLMediaRemoteCtrl* ) data; - - LLMediaRemoteCtrlEvent event ( self, 0.0f ); - self->mediaRemoteCtrlEventEmitter.update ( &LLMediaRemoteCtrlObserver::onPauseButtonPressed, event ); + return LL_MEDIA_REMOTE_CTRL_TAG; } //////////////////////////////////////////////////////////////////////////////// // // -void -LLMediaRemoteCtrl:: -onStopButton ( void* data ) +void LLMediaRemoteCtrl::draw() { - LLMediaRemoteCtrl* self = ( LLMediaRemoteCtrl* ) data; - - LLMediaRemoteCtrlEvent event ( self, 0.0f ); - self->mediaRemoteCtrlEventEmitter.update ( &LLMediaRemoteCtrlObserver::onStopButtonPressed, event ); + LLOverlayBar::enableMusicButtons(this); + LLOverlayBar::enableMediaButtons(this); + LLPanel::draw(); + // make volume button reflect of volume floater + childSetValue("volume", LLFloaterAudioVolume::instanceVisible(LLSD())); } - diff --git a/linden/indra/newview/llmediaremotectrl.h b/linden/indra/newview/llmediaremotectrl.h index 605be04..4f4ba77 100644 --- a/linden/indra/newview/llmediaremotectrl.h +++ b/linden/indra/newview/llmediaremotectrl.h @@ -30,94 +30,24 @@ #define LL_LLMEDIAREMOTECTRL_H #include "llpanel.h" -#include "llvolumesliderctrl.h" -#include "lleventemitter.h" //////////////////////////////////////////////////////////////////////////////// // -class LLMediaRemoteCtrlEvent -{ - public: - LLMediaRemoteCtrlEvent ( LLUICtrl* controlIn, F32 valueIn ): - control ( controlIn ), - value ( valueIn ) - { - }; - - virtual ~LLMediaRemoteCtrlEvent () { } - - LLUICtrl* getControl () const { return control; }; - F32 getValue () const { return value; }; - - private: - LLUICtrl* control; - F32 value; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -class LLMediaRemoteCtrlObserver +class LLMediaRemoteCtrl : public LLPanel { public: - typedef LLMediaRemoteCtrlEvent EventType; - virtual ~LLMediaRemoteCtrlObserver() {} - virtual void onVolumeChange ( const EventType& eventIn ) { }; - virtual void onStopButtonPressed ( const EventType& eventIn ) { }; - virtual void onPlayButtonPressed ( const EventType& eventIn ) { }; - virtual void onPauseButtonPressed ( const EventType& eventIn ) { }; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -class LLMediaRemoteCtrl : - public LLPanel -{ - public: - LLMediaRemoteCtrl ( const std::string& name, - const std::string& label, - const LLRect& rect, - const std::string& xml_file ); + LLMediaRemoteCtrl ( const LLString& name, + const LLString& label, + const LLRect& rect, + const LLString& xml_file ); - virtual ~LLMediaRemoteCtrl (); - - virtual EWidgetType getWidgetType() const; - virtual LLString getWidgetTag() const; - - // set current transport state of remote control - enum TransportState { Stop, Play, Pause }; - void setTransportState ( TransportState transportStateIn, BOOL pauseEnabled ); - TransportState getTransportState (); - void setVolume ( F32 volumeIn ); - - // allow consumers to observe remote control events - virtual BOOL addObserver ( LLMediaRemoteCtrlObserver* observerIn ) - { - return mediaRemoteCtrlEventEmitter.addObserver ( observerIn ); - }; - virtual BOOL remObserver ( LLMediaRemoteCtrlObserver* observerIn ) - { - return mediaRemoteCtrlEventEmitter.remObserver ( observerIn ); - }; + virtual ~LLMediaRemoteCtrl (); + virtual BOOL postBuild(); - private: - LLVolumeSliderCtrl* mVolumeSlider; - LLRect volumeSliderRect; - - TransportState transportState; - - LLTextBox* titleLabel; - LLButton* playButton; - LLButton* pauseButton; - LLButton* stopButton; - - // event emitter - eventEmitter < LLMediaRemoteCtrlObserver > mediaRemoteCtrlEventEmitter; - - // callbacks - static void onCommitVolume ( LLUICtrl* ctrl, void* data ); - static void onPlayButton ( void* data ); - static void onPauseButton ( void* data ); - static void onStopButton ( void* data ); + virtual void draw(); + + virtual EWidgetType getWidgetType() const; + virtual LLString getWidgetTag() const; }; #endif diff --git a/linden/indra/newview/llmemoryview.cpp b/linden/indra/newview/llmemoryview.cpp index 1d92bff..c29b33f 100644 --- a/linden/indra/newview/llmemoryview.cpp +++ b/linden/indra/newview/llmemoryview.cpp @@ -45,10 +45,20 @@ #include "llfasttimer.h" + + LLMemoryView::LLMemoryView(const std::string& name, const LLRect& rect) -: LLView(name, rect, TRUE) +: LLView(name, rect, TRUE), +mDelay(120) { setVisible(FALSE); + mDumpTimer.reset(); + +#ifdef MEM_DUMP_DATA + // clear out file. + FILE *dump = fopen("memusagedump.txt", "w"); + fclose(dump); +#endif } LLMemoryView::~LLMemoryView() @@ -196,7 +206,7 @@ void LLMemoryView::draw() peak += maxbytes; S32 mbytes = bytes >> 20; - tdesc = llformat("%s [%4d MB]",mtv_display_table[i].desc,mbytes); + tdesc = llformat("%s [%4d MB] in %06d NEWS",mtv_display_table[i].desc,mbytes, LLMemType::sNewCount[tidx]); LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); y -= (texth + 2); @@ -239,7 +249,46 @@ void LLMemoryView::draw() y -= (texth + 2); } + dumpData(); + #endif LLView::draw(); } + +void LLMemoryView::setDataDumpInterval(float delay) +{ + mDelay = delay; +} + +void LLMemoryView::dumpData() +{ +#if MEM_TRACK_TYPE && MEM_DUMP_DATA + if (mDelay && (mDumpTimer.getElapsedTimeF32() > mDelay )) + { + // reset timer + mDumpTimer.reset(); + // append dump info to text file + FILE *dump = fopen("memusagedump.txt", "a"); + + if (dump) + { + // write out total memory usage + fprintf (dump, "Total memory in use = %09d (%03d MB)\n", LLMemType::sTotalMem, LLMemType::sTotalMem>>20); + fprintf (dump, "High Water Mark = %09d (%03d MB)\n\n", LLMemType::sMaxTotalMem, LLMemType::sMaxTotalMem>>20); + // dump out usage of 'new' for each memory type + for (S32 i=0; i>20, LLMemType::sMaxMemCount[i], LLMemType::sMaxMemCount[i]>>20, LLMemType::sNewCount[i]); + fprintf (dump, "%s\n", outData.c_str()); + } + } + fprintf (dump, "\n\n"); + + fclose(dump); + } + } +#endif +} diff --git a/linden/indra/newview/llmemoryview.h b/linden/indra/newview/llmemoryview.h index 6d5b96b..809e40f 100644 --- a/linden/indra/newview/llmemoryview.h +++ b/linden/indra/newview/llmemoryview.h @@ -46,6 +46,13 @@ public: virtual void draw(); private: + void setDataDumpInterval(float delay); + void dumpData(); + + float mDelay; + LLFrameTimer mDumpTimer; + +private: }; #endif diff --git a/linden/indra/newview/llmutelist.cpp b/linden/indra/newview/llmutelist.cpp index bca9080..b5764c5 100644 --- a/linden/indra/newview/llmutelist.cpp +++ b/linden/indra/newview/llmutelist.cpp @@ -189,11 +189,11 @@ BOOL LLMuteList::isLinden(const LLString& name) const } -BOOL LLMuteList::add(const LLMute& mute) +BOOL LLMuteList::add(const LLMute& mute, U32 flags) { - // Can't mute Lindens + // Can't mute text from Lindens if ((mute.mType == LLMute::AGENT || mute.mType == LLMute::BY_NAME) - && isLinden(mute.mName)) + && isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0)) { gViewerWindow->alertXml("MuteLinden"); return FALSE; @@ -238,25 +238,59 @@ BOOL LLMuteList::add(const LLMute& mute) } else { - std::pair result = mMutes.insert(mute); - if (result.second) + // Need a local (non-const) copy to set up flags properly. + LLMute localmute = mute; + + // If an entry for the same entity is already in the list, remove it, saving flags as necessary. + mute_set_t::iterator it = mMutes.find(localmute); + if (it != mMutes.end()) { - llinfos << "Muting " << mute.mName << " id " << mute.mID << llendl; - updateAdd(mute); - notifyObservers(); - //Kill all particle systems owned by muted task - if(mute.mType == LLMute::AGENT || mute.mType == LLMute::OBJECT) - { - gWorldPointer->mPartSim.cleanMutedParticles(mute.mID); - } + // This mute is already in the list. Save the existing entry's flags if that's warranted. + localmute.mFlags = it->mFlags; + + mMutes.erase(it); + // Don't need to call notifyObservers() here, since it will happen after the entry has been re-added below. + } + else + { + // There was no entry in the list previously. Fake things up by making it look like the previous entry had all properties unmuted. + localmute.mFlags = LLMute::flagAll; + } - return TRUE; + if(flags) + { + // The user passed some combination of flags. Make sure those flag bits are turned off (i.e. those properties will be muted). + localmute.mFlags &= (~flags); } else { - return FALSE; + // The user passed 0. Make sure all flag bits are turned off (i.e. all properties will be muted). + localmute.mFlags = 0; + } + + // (re)add the mute entry. + { + std::pair result = mMutes.insert(localmute); + if (result.second) + { + llinfos << "Muting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl; + updateAdd(mute); + notifyObservers(); + if(!(localmute.mFlags & LLMute::flagParticles)) + { + //Kill all particle systems owned by muted task + if(localmute.mType == LLMute::AGENT || localmute.mType == LLMute::OBJECT) + { + gWorldPointer->mPartSim.cleanMutedParticles(localmute.mID); + } + } + return TRUE; + } } } + + // If we were going to return success, we'd have done it by now. + return FALSE; } void LLMuteList::updateAdd(const LLMute& mute) @@ -271,14 +305,14 @@ void LLMuteList::updateAdd(const LLMute& mute) msg->addUUIDFast(_PREHASH_MuteID, mute.mID); msg->addStringFast(_PREHASH_MuteName, mute.mName); msg->addS32("MuteType", mute.mType); - msg->addU32("MuteFlags", 0x0); // future + msg->addU32("MuteFlags", mute.mFlags); gAgent.sendReliableMessage(); mIsLoaded = TRUE; } -BOOL LLMuteList::remove(const LLMute& mute) +BOOL LLMuteList::remove(const LLMute& mute, U32 flags) { BOOL found = FALSE; @@ -286,8 +320,46 @@ BOOL LLMuteList::remove(const LLMute& mute) mute_set_t::iterator it = mMutes.find(mute); if (it != mMutes.end()) { - updateRemove(*it); + LLMute localmute = *it; + bool remove = true; + if(flags) + { + // If the user passed mute flags, we may only want to turn some flags on. + localmute.mFlags |= flags; + + if(localmute.mFlags == LLMute::flagAll) + { + // Every currently available mute property has been masked out. + // Remove the mute entry entirely. + } + else + { + // Only some of the properties are masked out. Update the entry. + remove = false; + } + } + else + { + // The caller didn't pass any flags -- just remove the mute entry entirely. + } + + // Always remove the entry from the set -- it will be re-added with new flags if necessary. mMutes.erase(it); + + if(remove) + { + // The entry was actually removed. Notify the server. + updateRemove(localmute); + llinfos << "Unmuting " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl; + } + else + { + // Flags were updated, the mute entry needs to be retransmitted to the server and re-added to the list. + mMutes.insert(localmute); + updateAdd(localmute); + llinfos << "Updating mute entry " << localmute.mName << " id " << localmute.mID << " flags " << localmute.mFlags << llendl; + } + // Must be after erase. notifyObservers(); found = TRUE; @@ -381,7 +453,7 @@ BOOL LLMuteList::loadFromFile(const LLString& filename) buffer, " %d %254s %254[^|]| %u\n", &type, id_buffer, name_buffer, &flags); LLUUID id = LLUUID(id_buffer); - LLMute mute(id, name_buffer, (LLMute::EType)type); + LLMute mute(id, name_buffer, (LLMute::EType)type, flags); if (mute.mID.isNull() || mute.mType == LLMute::BY_NAME) { @@ -430,19 +502,27 @@ BOOL LLMuteList::saveToFile(const LLString& filename) { it->mID.toString(id_string); const LLString& name = it->mName; - fprintf(fp, "%d %s %s|\n", (S32)it->mType, id_string, name.c_str()); + fprintf(fp, "%d %s %s|%u\n", (S32)it->mType, id_string, name.c_str(), it->mFlags); } fclose(fp); return TRUE; } -BOOL LLMuteList::isMuted(const LLUUID& id, const LLString& name) const +BOOL LLMuteList::isMuted(const LLUUID& id, const LLString& name, U32 flags) const { // don't need name or type for lookup LLMute mute(id); mute_set_t::const_iterator mute_it = mMutes.find(mute); - if (mute_it != mMutes.end()) return TRUE; + if (mute_it != mMutes.end()) + { + // If any of the flags the caller passed are set, this item isn't considered muted for this caller. + if(flags & mute_it->mFlags) + { + return FALSE; + } + return TRUE; + } // empty names can't be legacy-muted if (name.empty()) return FALSE; diff --git a/linden/indra/newview/llmutelist.h b/linden/indra/newview/llmutelist.h index d8f1bf6..4624bfd 100644 --- a/linden/indra/newview/llmutelist.h +++ b/linden/indra/newview/llmutelist.h @@ -43,8 +43,22 @@ public: // Legacy mutes are BY_NAME and have null UUID. enum EType { BY_NAME = 0, AGENT = 1, OBJECT = 2, GROUP = 3, COUNT = 4 }; - LLMute(const LLUUID& id, const LLString& name = "", EType type = BY_NAME) - : mID(id), mName(name), mType(type) { } + // Bits in the mute flags. For backwards compatibility (since any mute list entries that were created before the flags existed + // will have a flags field of 0), some of the flags are "inverted". + // Note that it's possible, through flags, to completely disable an entry in the mute list. The code should detect this case + // and remove the mute list entry instead. + enum + { + flagTextChat = 0x00000001, // If set, don't mute user's text chat + flagVoiceChat = 0x00000002, // If set, don't mute user's voice chat + flagParticles = 0x00000004, // If set, don't mute user's particles + flagObjectSounds = 0x00000008, // If set, mute user's object sounds + + flagAll = 0x0000000F // Mask of all currently defined flags + }; + + LLMute(const LLUUID& id, const LLString& name = "", EType type = BY_NAME, U32 flags = 0) + : mID(id), mName(name), mType(type),mFlags(flags) { } // Returns name + suffix based on type // For example: "James Tester (resident)" @@ -59,6 +73,7 @@ public: LLUUID mID; // agent or object id LLString mName; // agent or object name EType mType; // needed for UI display of existing mutes + U32 mFlags; // flags pertaining to this mute entry }; class LLMuteList @@ -70,14 +85,17 @@ public: void addObserver(LLMuteListObserver* observer); void removeObserver(LLMuteListObserver* observer); - // Add either a normal or a BY_NAME mute. - BOOL add(const LLMute& mute); + // Add either a normal or a BY_NAME mute, for any or all properties. + BOOL add(const LLMute& mute, U32 flags = 0); - // Remove both normal and legacy mutes. - BOOL remove(const LLMute& mute); + // Remove both normal and legacy mutes, for any or all properties. + BOOL remove(const LLMute& mute, U32 flags = 0); // Name is required to test against legacy text-only mutes. - BOOL isMuted(const LLUUID& id, const LLString& name = LLString::null) const; + BOOL isMuted(const LLUUID& id, const LLString& name = LLString::null, U32 flags = 0) const; + + // Alternate (convenience) form for places we don't need to pass the name, but do need flags + BOOL isMuted(const LLUUID& id, U32 flags) const { return isMuted(id, LLString::null, flags); }; BOOL isLinden(const LLString& name) const; diff --git a/linden/indra/newview/llnetmap.cpp b/linden/indra/newview/llnetmap.cpp index 2105521..4701aae 100644 --- a/linden/indra/newview/llnetmap.cpp +++ b/linden/indra/newview/llnetmap.cpp @@ -246,7 +246,7 @@ void LLNetMap::draw() { LLGLSNoTexture no_texture; - LLUI::setScissorRegionLocal(LLRect(0, mRect.getHeight(), mRect.getWidth(), 0)); + LLLocalClipRect clip(getLocalRect()); glMatrixMode(GL_MODELVIEW); diff --git a/linden/indra/newview/llnotify.cpp b/linden/indra/newview/llnotify.cpp index 7822d00..4f5c64b 100644 --- a/linden/indra/newview/llnotify.cpp +++ b/linden/indra/newview/llnotify.cpp @@ -58,48 +58,106 @@ const F32 ANIMATION_TIME = 0.333f; S32 LLNotifyBox::sNotifyBoxCount = 0; const LLFontGL* LLNotifyBox::sFont = NULL; const LLFontGL* LLNotifyBox::sFontSmall = NULL; +std::map LLNotifyBox::sOpenUniqueNotifyBoxes; +LLPointer LLNotifyBox::sDefaultTemplate; + LLNotifyBox::template_map_t LLNotifyBox::sNotifyTemplates; +LLNotifyBox::LLNotifyBehavior::LLNotifyBehavior(notify_callback_t callback, void* data) : + mCallback(callback), + mData(data) +{ +} + //--------------------------------------------------------------------------- // LLNotifyBox //--------------------------------------------------------------------------- //static -void LLNotifyBox::showXml( const LLString& xml_desc, notify_callback_t callback, void *user_data) +LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, notify_callback_t callback, void *user_data) { return showXml(xml_desc, LLString::format_map_t(), callback, user_data); } //static -void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution, +LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution, notify_callback_t callback, void *user_data) { // for script permission prompts - LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data, is_caution); - gNotifyBoxView->addChild(notify); + LLPointer xml_template = getTemplate(xml_desc); + LLNotifyBox* notify = findExistingNotify(xml_template, args); + if (notify) + { + delete notify->mBehavior; + notify->mBehavior = new LLNotifyBehavior(callback, user_data); + } + else + { + LLNotifyBox* notify = new LLNotifyBox(xml_template, args, callback, user_data, is_caution); + gNotifyBoxView->addChildAtEnd(notify); + notify->moveToBack(); + } + return notify; } //static -void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, +LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, notify_callback_t callback, void *user_data) { - LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data); - gNotifyBoxView->addChild(notify); + LLPointer xml_template = getTemplate(xml_desc); + LLNotifyBox* notify = findExistingNotify(xml_template, args); + if (notify) + { + delete notify->mBehavior; + notify->mBehavior = new LLNotifyBehavior(callback, user_data); + } + else + { + notify = new LLNotifyBox(xml_template, args, callback, user_data); + gNotifyBoxView->addChildAtEnd(notify); + notify->moveToBack(); + } + return notify; } //static -void LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, +LLNotifyBox* LLNotifyBox::showXml( const LLString& xml_desc, const LLString::format_map_t& args, notify_callback_t callback, void *user_data, const option_list_t& options, BOOL layout_script_dialog) { - LLNotifyBox* notify = new LLNotifyBox(xml_desc, args, callback, user_data, FALSE, options, layout_script_dialog); - gNotifyBoxView->addChild(notify); + LLPointer xml_template = getTemplate(xml_desc); + LLNotifyBox* notify = findExistingNotify(xml_template, args); + if (notify) + { + delete notify->mBehavior; + notify->mBehavior = new LLNotifyBehavior(callback, user_data); + } + else + { + notify = new LLNotifyBox(xml_template, args, callback, user_data, FALSE, options, layout_script_dialog); + gNotifyBoxView->addChild(notify); + } + return notify; } -LLPointer LLNotifyBox::sDefaultTemplate; +//static +LLNotifyBox* LLNotifyBox::findExistingNotify(LLPointer notify_template, const LLString::format_map_t &args) +{ + if(notify_template->mUnique) + { + LLString message = notify_template->mMessage; + LLAlertDialog::format(message, args); + unique_map_t::iterator found_it = sOpenUniqueNotifyBoxes.find(notify_template->mLabel + message); + if (found_it != sOpenUniqueNotifyBoxes.end()) + { + return found_it->second; + } + } + return NULL; +} void LLNotifyBox::cleanup() { @@ -108,18 +166,17 @@ void LLNotifyBox::cleanup() //--------------------------------------------------------------------------- -LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& args, +LLNotifyBox::LLNotifyBox(LLPointer xml_template, const LLString::format_map_t& args, notify_callback_t callback, void* user_data, BOOL is_caution, const option_list_t& extra_options, BOOL layout_script_dialog) - : LLPanel("notify", LLRect(), BORDER_NO), - LLEventTimer(gSavedSettings.getF32("NotifyTipDuration")), + : LLPanel(xml_template->mLabel, LLRect(), BORDER_NO), + LLEventTimer(xml_template->mDuration), mIsTip(FALSE), mAnimating(TRUE), - mTimer(), + mUnique(xml_template->mUnique), mNextBtn(NULL), - mCallback(callback), - mData(user_data), + mBehavior(new LLNotifyBehavior(callback, user_data)), mNumOptions(0), mDefaultOption(0) { @@ -133,31 +190,17 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& sFontSmall = LLFontGL::sSansSerifSmall; } - // get template - - if (!sDefaultTemplate) - { - sDefaultTemplate = new LLNotifyBoxTemplate; - } + // setup paramaters - LLPointer xml_template; - template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); - if (iter != sNotifyTemplates.end()) - { - xml_template = iter->second; - } - else + mMessage = xml_template->mMessage; + LLAlertDialog::format(mMessage, args); + + // use name + formatted text as unique key + if (mUnique) { - LLString tmsg = "[Notification template not found:\n " + xml_desc + " ]"; - sDefaultTemplate->setMessage(tmsg); - xml_template = sDefaultTemplate; + sOpenUniqueNotifyBoxes[xml_template->mLabel + mMessage] = this; } - // setup paramaters - - LLString message = xml_template->mMessage; - LLAlertDialog::format(message, args); - option_list_t options = xml_template->mOptions; options.insert(options.end(), extra_options.begin(), extra_options.end()); @@ -175,13 +218,16 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& // account for the special layout of a tip notification) mIsCaution = ((xml_template->mIsCaution | is_caution) && (!mIsTip)); - mAnimating = TRUE; - mCallback = callback; - mData = user_data; + // Don't animate if behind other windows + if( gNotifyBoxView->getChildCount() > 0 ) + mAnimating = FALSE; + else + mAnimating = TRUE; + mNumOptions = options.size(); mDefaultOption = xml_template->mDefaultOption; - LLRect rect = mIsTip ? getNotifyTipRect(message) + LLRect rect = mIsTip ? getNotifyTipRect(mMessage) : getNotifyRect(mNumOptions, layout_script_dialog, mIsCaution); setRect(rect); setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT)); @@ -255,7 +301,7 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& text = new LLTextEditor("box", LLRect(x, y, mRect.getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, - message, + mMessage, sFont, FALSE); text->setWordWrap(TRUE); @@ -275,15 +321,15 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& if (mIsTip) { // TODO: Make a separate archive for these. - LLChat chat(message); + LLChat chat(mMessage); chat.mSourceType = CHAT_SOURCE_SYSTEM; - gFloaterChat->addChatHistory(chat); + LLFloaterChat::getInstance(LLSD())->addChatHistory(chat); } else { LLButton* btn; btn = new LLButton("next", - LLRect(mRect.getWidth()-24, BOTTOM_PAD+16, mRect.getWidth()-8, BOTTOM_PAD), + LLRect(mRect.getWidth()-18, BOTTOM_PAD+16, mRect.getWidth()-2, BOTTOM_PAD+2), "notify_next.tga", "notify_next.tga", "", @@ -328,7 +374,7 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& userdata->mSelf = this; userdata->mButton = i; - mBtnCallbackData.put(userdata); + mBtnCallbackData.push_back(userdata); btn = new LLButton(options[i], btn_rect, "", onClickButton, userdata); btn->setFont(font); @@ -361,10 +407,14 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& // virtual LLNotifyBox::~LLNotifyBox() { - S32 count = mBtnCallbackData.count(); - for (S32 i = 0; i < count; i++) + delete mBehavior; + mBehavior = NULL; + + std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); + + if (mUnique) { - delete mBtnCallbackData[i]; + sOpenUniqueNotifyBoxes.erase(mName + mMessage); } } @@ -398,7 +448,7 @@ BOOL LLNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask) // virtual void LLNotifyBox::draw() { - F32 display_time = mTimer.getElapsedTimeF32(); + F32 display_time = mAnimateTimer.getElapsedTimeF32(); if (mAnimating && display_time < ANIMATION_TIME) { @@ -492,7 +542,10 @@ void LLNotifyBox::close() gNotifyBoxView->showOnly(front); // we're assuming that close is only called by user action (for non-tips), // so we then give focus to the next close button - front->mDefaultBtn->setFocus(TRUE); + if (front->mDefaultBtn) + { + front->mDefaultBtn->setFocus(TRUE); + } gFocusMgr.triggerFocusFlash(); // TODO it's ugly to call this here } } @@ -681,9 +734,9 @@ void LLNotifyBox::onClickButton(void* data) return; } - if (self->mCallback) + if (self->mBehavior->mCallback) { - self->mCallback(button, self->mData); + self->mBehavior->mCallback(button, self->mBehavior->mData); } self->close(); @@ -697,10 +750,54 @@ void LLNotifyBox::onClickNext(void* data) self->moveToBack(); } +// static +LLPointer LLNotifyBox::getTemplate(const LLString& xml_desc) +{ + // get template + + if (!sDefaultTemplate) + { + // default template is non-unique, of course + sDefaultTemplate = new LLNotifyBoxTemplate(FALSE, gSavedSettings.getF32("NotifyTipDuration")); + sDefaultTemplate->addOption("OK", FALSE); + } + + LLPointer xml_template; + template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); + if (iter != sNotifyTemplates.end()) + { + xml_template = iter->second; + } + else + { + LLString tmsg = "[Notification template not found:\n " + xml_desc + " ]"; + sDefaultTemplate->setMessage(tmsg); + xml_template = sDefaultTemplate; + } + + return xml_template; +} + //----------------------------------------------------------------------------- //static -const LLString& LLNotifyBox::getTemplateMessage(const LLString& xml_desc) +const LLString LLNotifyBox::getTemplateMessage(const LLString& xml_desc, const LLString::format_map_t& args) +{ + template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); + if (iter != sNotifyTemplates.end()) + { + LLString message = iter->second->mMessage; + LLAlertDialog::format(message, args); + return message; + } + else + { + return xml_desc; + } +} + +//static +const LLString LLNotifyBox::getTemplateMessage(const LLString& xml_desc) { template_map_t::iterator iter = sNotifyTemplates.find(xml_desc); if (iter != sNotifyTemplates.end()) @@ -747,8 +844,14 @@ bool LLNotifyBox::parseNotify(const LLString& xml_filename) { continue; } + + BOOL unique = FALSE; + notify->getAttributeBOOL("unique", unique); + + F32 duration = gSavedSettings.getF32("NotifyTipDuration"); + notify->getAttributeF32("duration", duration); - LLPointer xml_template = new LLNotifyBoxTemplate; + LLPointer xml_template = new LLNotifyBoxTemplate(unique, duration); // label= LLString notify_name; diff --git a/linden/indra/newview/llnotify.h b/linden/indra/newview/llnotify.h index eec27ec..ad9b24a 100644 --- a/linden/indra/newview/llnotify.h +++ b/linden/indra/newview/llnotify.h @@ -31,8 +31,8 @@ #include "llfontgl.h" #include "llpanel.h" -#include "lldarray.h" #include "lltimer.h" +#include class LLButton; class LLNotifyBoxTemplate; @@ -44,33 +44,36 @@ public: typedef void (*notify_callback_t)(S32 option, void* data); typedef std::vector option_list_t; - static void showXml( const LLString& xml_desc, + static LLNotifyBox* showXml( const LLString& xml_desc, notify_callback_t callback = NULL, void *user_data = NULL); - static void showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution, + static LLNotifyBox* showXml( const LLString& xml_desc, const LLString::format_map_t& args, BOOL is_caution, notify_callback_t callback = NULL, void *user_data = NULL); - static void showXml( const LLString& xml_desc, const LLString::format_map_t& args, + static LLNotifyBox* showXml( const LLString& xml_desc, const LLString::format_map_t& args, notify_callback_t callback = NULL, void *user_data = NULL); // For script notifications: - static void showXml( const LLString& xml_desc, const LLString::format_map_t& args, + static LLNotifyBox* showXml( const LLString& xml_desc, const LLString::format_map_t& args, notify_callback_t callback, void *user_data, const option_list_t& options, BOOL layout_script_dialog = FALSE); static bool parseNotify(const LLString& xml_filename); - static const LLString& getTemplateMessage(const LLString& xml_desc); + static const LLString getTemplateMessage(const LLString& xml_desc, const LLString::format_map_t& args); + static const LLString getTemplateMessage(const LLString& xml_desc); static BOOL getTemplateIsCaution(const LLString& xml_desc); BOOL isTip() const { return mIsTip; } BOOL isCaution() const { return mIsCaution; } /*virtual*/ void setVisible(BOOL visible); + void stopAnimation() { mAnimating = FALSE; } - notify_callback_t getNotifyCallback() { return mCallback; } - void* getUserData() { return mData; } + notify_callback_t getNotifyCallback() { return mBehavior->mCallback; } + void* getUserData() { return mBehavior->mData; } + void close(); static void cleanup(); protected: - LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& args, + LLNotifyBox(LLPointer notify_template, const LLString::format_map_t& args, notify_callback_t callback, void* user_data, BOOL is_caution = FALSE, const option_list_t& extra_options = option_list_t(), @@ -85,7 +88,6 @@ protected: /*virtual*/ void draw(); /*virtual*/ void tick(); - void close(); void moveToBack(); // Returns the rect, relative to gNotifyView, where this @@ -99,25 +101,40 @@ protected: // for "next" button static void onClickNext(void* data); + static LLPointer getTemplate(const LLString& xml_desc); + static LLNotifyBox* findExistingNotify(LLPointer notify_template, const LLString::format_map_t& args); + private: void drawBackground() const; static LLPointer sDefaultTemplate; protected: + LLString mMessage; + BOOL mIsTip; BOOL mIsCaution; // is this a caution notification? BOOL mAnimating; // Are we sliding onscreen? + BOOL mUnique; // Time since this notification was displayed. // This is an LLTimer not a frame timer because I am concerned // that I could be out-of-sync by one frame in the animation. - LLTimer mTimer; + LLTimer mAnimateTimer; LLButton* mNextBtn; - notify_callback_t mCallback; - void* mData; + // keep response behavior isolated here + struct LLNotifyBehavior + { + LLNotifyBehavior(notify_callback_t callback, void* data); + + notify_callback_t mCallback; + void* mData; + + }; + LLNotifyBehavior* mBehavior; + S32 mNumOptions; S32 mDefaultOption; @@ -127,7 +144,7 @@ protected: LLNotifyBox* mSelf; S32 mButton; }; - LLDynamicArray mBtnCallbackData; + std::vector mBtnCallbackData; typedef std::map > template_map_t; static template_map_t sNotifyTemplates; // by mLabel @@ -135,6 +152,9 @@ protected: static S32 sNotifyBoxCount; static const LLFontGL* sFont; static const LLFontGL* sFontSmall; + + typedef std::map unique_map_t; + static unique_map_t sOpenUniqueNotifyBoxes; }; class LLNotifyBoxView : public LLUICtrl @@ -154,7 +174,13 @@ extern LLNotifyBoxView* gNotifyBoxView; class LLNotifyBoxTemplate : public LLRefCount { public: - LLNotifyBoxTemplate() : mIsTip(FALSE), mIsCaution(FALSE), mDefaultOption(0) {} + LLNotifyBoxTemplate(BOOL unique, F32 duration) : + mIsTip(FALSE), + mIsCaution(FALSE), + mUnique(unique), + mDuration(duration), + mDefaultOption(0) + {} void setMessage(const LLString& message) { @@ -174,7 +200,9 @@ public: LLString mLabel; // Handle for access from code, etc LLString mMessage; // Message to display BOOL mIsTip; - BOOL mIsCaution; + BOOL mIsCaution; + BOOL mUnique; + F32 mDuration; LLNotifyBox::option_list_t mOptions; S32 mDefaultOption; }; diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp index 401cb02..f5addd0 100644 --- a/linden/indra/newview/lloverlaybar.cpp +++ b/linden/indra/newview/lloverlaybar.cpp @@ -34,24 +34,26 @@ #include "lloverlaybar.h" #include "audioengine.h" -#include "llparcel.h" - #include "llagent.h" #include "llbutton.h" -#include "llviewercontrol.h" +#include "llfocusmgr.h" #include "llimview.h" -#include "lltextbox.h" -#include "llvoavatar.h" #include "llmediaengine.h" -#include "viewer.h" +#include "llpanelaudiovolume.h" +#include "llparcel.h" +#include "lltextbox.h" #include "llui.h" +#include "llviewercontrol.h" +#include "llviewerimagelist.h" #include "llviewermenu.h" // handle_reset_view() #include "llviewerparcelmgr.h" -#include "llwebbrowserctrl.h" #include "llvieweruictrlfactory.h" -#include "llviewerimagelist.h" #include "llviewerwindow.h" -#include "llfocusmgr.h" +#include "llvoiceclient.h" +#include "llvoavatar.h" +#include "llvoiceremotectrl.h" +#include "llwebbrowserctrl.h" +#include "viewer.h" // // Globals @@ -67,38 +69,54 @@ extern S32 MENU_BAR_HEIGHT; //static -void* LLOverlayBar::createMediaRemote(void* userdata) +void* LLOverlayBar::createMasterRemote(void* userdata) { - - LLOverlayBar *self = (LLOverlayBar*)userdata; + LLOverlayBar *self = (LLOverlayBar*)userdata; + self->mMasterRemote = new LLMediaRemoteCtrl ( "master_volume", + "volume", + LLRect(), + "panel_master_volume.xml"); + return self->mMasterRemote; +} - +void* LLOverlayBar::createMediaRemote(void* userdata) +{ + LLOverlayBar *self = (LLOverlayBar*)userdata; self->mMediaRemote = new LLMediaRemoteCtrl ( "media_remote", - "media", - LLRect(), - "panel_media_remote.xml"); + "media", + LLRect(), + "panel_media_remote.xml"); return self->mMediaRemote; } - - void* LLOverlayBar::createMusicRemote(void* userdata) { - LLOverlayBar *self = (LLOverlayBar*)userdata; - self->mMusicRemote = new LLMediaRemoteCtrl ( "music_remote", - "music", - LLRect(), - "panel_music_remote.xml" ); + "music", + LLRect(), + "panel_music_remote.xml" ); return self->mMusicRemote; } +void* LLOverlayBar::createVoiceRemote(void* userdata) +{ + LLOverlayBar *self = (LLOverlayBar*)userdata; + self->mVoiceRemote = new LLVoiceRemoteCtrl("voice_remote"); + return self->mVoiceRemote; +} + LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect) -: LLPanel(name, rect, FALSE) // not bordered + : LLPanel(name, rect, FALSE), // not bordered + mMasterRemote(NULL), + mMusicRemote(NULL), + mMediaRemote(NULL), + mVoiceRemote(NULL), + mMediaState(STOPPED), + mMusicState(STOPPED) { setMouseOpaque(FALSE); setIsChrome(TRUE); @@ -106,8 +124,10 @@ LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect) isBuilt = FALSE; LLCallbackMap::map_t factory_map; + factory_map["master_volume"] = LLCallbackMap(LLOverlayBar::createMasterRemote, this); factory_map["media_remote"] = LLCallbackMap(LLOverlayBar::createMediaRemote, this); factory_map["music_remote"] = LLCallbackMap(LLOverlayBar::createMusicRemote, this); + factory_map["voice_remote"] = LLCallbackMap(LLOverlayBar::createVoiceRemote, this); gUICtrlFactory->buildPanel(this, "panel_overlaybar.xml", &factory_map); @@ -117,30 +137,17 @@ LLOverlayBar::LLOverlayBar(const std::string& name, const LLRect& rect) childSetAction("Mouselook",onClickMouselook,this); childSetAction("Stand Up",onClickStandUp,this); - mMusicRemote->addObserver ( this ); - - if ( gAudiop ) - { - mMusicRemote->setVolume ( gSavedSettings.getF32 ( "AudioLevelMusic" ) ); - mMusicRemote->setTransportState ( LLMediaRemoteCtrl::Stop, FALSE ); - }; - mIsFocusRoot = TRUE; - - mMediaRemote->addObserver ( this ); - mMediaRemote->setVolume ( gSavedSettings.getF32 ( "MediaAudioVolume" ) ); - isBuilt = true; + // make overlay bar conform to window size + setRect(rect); layoutButtons(); } LLOverlayBar::~LLOverlayBar() { // LLView destructor cleans up children - - mMusicRemote->remObserver ( this ); - mMediaRemote->remObserver ( this ); } EWidgetType LLOverlayBar::getWidgetType() const @@ -164,20 +171,28 @@ void LLOverlayBar::reshape(S32 width, S32 height, BOOL called_from_parent) } } - void LLOverlayBar::layoutButtons() { S32 width = mRect.getWidth(); - if (width > 800) width = 800; + if (width > 1024) width = 1024; S32 count = getChildCount(); const S32 PAD = gSavedSettings.getS32("StatusBarPad"); - F32 segment_width = (F32)(width) / (F32)count; + const S32 num_media_controls = 3; + S32 media_remote_width = mMediaRemote ? mMediaRemote->getRect().getWidth() : 0; + S32 music_remote_width = mMusicRemote ? mMusicRemote->getRect().getWidth() : 0; + S32 voice_remote_width = mVoiceRemote ? mVoiceRemote->getRect().getWidth() : 0; + S32 master_remote_width = mMasterRemote ? mMasterRemote->getRect().getWidth() : 0; - S32 btn_width = lltrunc(segment_width - PAD); + // total reserved width for all media remotes + const S32 ENDPAD = 20; + S32 remote_total_width = media_remote_width + PAD + music_remote_width + PAD + voice_remote_width + PAD + master_remote_width + ENDPAD; - S32 remote_width = mMusicRemote->getRect().getWidth(); + // calculate button widths + F32 segment_width = (F32)(width - remote_total_width) / (F32)(count - num_media_controls); + + S32 btn_width = lltrunc(segment_width - PAD); // Evenly space all views LLRect r; @@ -187,22 +202,47 @@ void LLOverlayBar::layoutButtons() { LLView *view = *child_iter; r = view->getRect(); - r.mLeft = (width) - llround((i+1)*segment_width); + r.mLeft = (width) - llround(remote_total_width + (i-num_media_controls+1)*segment_width); r.mRight = r.mLeft + btn_width; view->setRect(r); i++; } // Fix up remotes to have constant width because they can't shrink - r = mMusicRemote->getRect(); - r.mRight = r.mLeft + remote_width; - mMusicRemote->setRect(r); - - r = mMediaRemote->getRect(); - r.mLeft = mMusicRemote->getRect().mRight + PAD; - r.mRight = r.mLeft + remote_width; - mMediaRemote->setRect(r); - + S32 right = mRect.getWidth() - remote_total_width - PAD; + if (mMediaRemote) + { + r = mMediaRemote->getRect(); + r.mLeft = right + PAD; + right = r.mLeft + media_remote_width; + r.mRight = right; + mMediaRemote->setRect(r); + } + if (mMusicRemote) + { + r = mMusicRemote->getRect(); + r.mLeft = right + PAD; + right = r.mLeft + music_remote_width; + r.mRight = right; + mMusicRemote->setRect(r); + } + if (mVoiceRemote) + { + r = mVoiceRemote->getRect(); + r.mLeft = right + PAD; + right = r.mLeft + voice_remote_width; + r.mRight = right; + mVoiceRemote->setRect(r); + } + if (mMasterRemote) + { + r = mMasterRemote->getRect(); + r.mLeft = right + PAD; + right = r.mLeft + master_remote_width; + r.mRight = right; + mMasterRemote->setRect(r); + } + updateRect(); } @@ -282,7 +322,7 @@ void LLOverlayBar::draw() // Per-frame updates of visibility void LLOverlayBar::refresh() { - BOOL im_received = gIMView->getIMReceived(); + BOOL im_received = gIMMgr->getIMReceived(); childSetVisible("IM Received", im_received); childSetEnabled("IM Received", im_received); @@ -313,10 +353,10 @@ void LLOverlayBar::refresh() } - if ( gAudiop ) + if ( mMusicRemote && gAudiop ) { LLParcel* parcel = gParcelMgr->getAgentParcel(); - if (!parcel + if (!parcel || !parcel->getMusicURL() || !parcel->getMusicURL()[0] || !gSavedSettings.getBOOL("AudioStreamingMusic")) @@ -332,50 +372,29 @@ void LLOverlayBar::refresh() } // if there is a url and a texture and media is enabled and available and media streaming is on... (phew!) - if ( LLMediaEngine::getInstance () && - LLMediaEngine::getInstance ()->getUrl ().length () && - LLMediaEngine::getInstance ()->getImageUUID ().notNull () && - LLMediaEngine::getInstance ()->isEnabled () && - LLMediaEngine::getInstance ()->isAvailable () && - gSavedSettings.getBOOL ( "AudioStreamingVideo" ) ) + if ( mMediaRemote ) { - // display remote control - mMediaRemote->setVisible ( TRUE ); - mMediaRemote->setEnabled ( TRUE ); - - if ( LLMediaEngine::getInstance ()->getMediaRenderer () ) + if (LLMediaEngine::getInstance () && + LLMediaEngine::getInstance ()->getUrl ().length () && + LLMediaEngine::getInstance ()->getImageUUID ().notNull () && + LLMediaEngine::getInstance ()->isEnabled () && + LLMediaEngine::getInstance ()->isAvailable () && + gSavedSettings.getBOOL ( "AudioStreamingVideo" ) ) { - if ( LLMediaEngine::getInstance ()->getMediaRenderer ()->isPlaying () || - LLMediaEngine::getInstance ()->getMediaRenderer ()->isLooping () ) - { - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Pause, TRUE ); - } - else - if ( LLMediaEngine::getInstance ()->getMediaRenderer ()->isPaused () ) - { - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Play, TRUE ); - } - else - { - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Stop, TRUE ); - }; - }; + // display remote control + mMediaRemote->setVisible ( TRUE ); + mMediaRemote->setEnabled ( TRUE ); + } + else + { + mMediaRemote->setVisible ( FALSE ); + mMediaRemote->setEnabled ( FALSE ); + } } - else + if (mVoiceRemote) { - mMediaRemote->setVisible ( FALSE ); - mMediaRemote->setEnabled ( FALSE ); - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Stop, TRUE ); - }; - - BOOL any_button = (childIsVisible("IM Received") - || childIsVisible("Set Not Busy") - || childIsVisible("Release Keys") - || childIsVisible("Mouselook") - || childIsVisible("Stand Up") - || mMusicRemote->getVisible() - || mMediaRemote->getVisible() ); - + mVoiceRemote->setVisible(LLVoiceClient::voiceEnabled()); + } // turn off the whole bar in mouselook if (gAgent.cameraMouselook()) @@ -384,8 +403,8 @@ void LLOverlayBar::refresh() } else { - setVisible(any_button); - }; + setVisible(TRUE); + } } //----------------------------------------------------------------------- @@ -395,7 +414,7 @@ void LLOverlayBar::refresh() // static void LLOverlayBar::onClickIMReceived(void*) { - gIMView->setFloaterOpen(TRUE); + gIMMgr->setFloaterOpen(TRUE); } @@ -431,134 +450,162 @@ void LLOverlayBar::onClickStandUp(void*) } //////////////////////////////////////////////////////////////////////////////// -// -// -void -LLOverlayBar:: -onVolumeChange ( const LLMediaRemoteCtrlObserver::EventType& eventIn ) -{ - LLUICtrl* control = eventIn.getControl (); - F32 value = eventIn.getValue (); +// static media helpers +// *TODO: Move this into an audio manager abstraction - if ( control == mMusicRemote ) +//static +void LLOverlayBar::mediaPlay(void*) +{ + if (!gOverlayBar) { - if (gAudiop) - { - gAudiop->setInternetStreamGain ( value ); - }; - gSavedSettings.setF32 ( "AudioLevelMusic", value ); + return; } - else - if ( control == mMediaRemote ) + gOverlayBar->mMediaState = PLAYING; // desired state + LLParcel* parcel = gParcelMgr->getAgentParcel(); + if (parcel) { - LLMediaEngine::getInstance ()->setVolume ( value ); - gSavedSettings.setF32 ( "MediaAudioVolume", value ); - - }; + LLString path(""); + LLMediaEngine::getInstance()->convertImageAndLoadUrl( true, false, path ); + } } - -//////////////////////////////////////////////////////////////////////////////// -// -// -void -LLOverlayBar:: -onStopButtonPressed ( const LLMediaRemoteCtrlObserver::EventType& eventIn ) +//static +void LLOverlayBar::mediaPause(void*) { - LLUICtrl* control = eventIn.getControl (); - - if ( control == mMusicRemote ) + if (!gOverlayBar) { - if ( gAudiop ) - { - gAudiop->stopInternetStream (); - }; - mMusicRemote->setTransportState ( LLMediaRemoteCtrl::Stop, FALSE ); + return; } - else - if ( control == mMediaRemote ) + gOverlayBar->mMediaState = PAUSED; // desired state + LLMediaEngine::getInstance()->pause(); +} +//static +void LLOverlayBar::mediaStop(void*) +{ + if (!gOverlayBar) { - LLMediaEngine::getInstance ()->stop (); - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Stop, TRUE ); - }; + return; + } + gOverlayBar->mMediaState = STOPPED; // desired state + LLMediaEngine::getInstance()->stop(); } -//////////////////////////////////////////////////////////////////////////////// -// -// -void LLOverlayBar::onPlayButtonPressed( const LLMediaRemoteCtrlObserver::EventType& eventIn ) +//static +void LLOverlayBar::musicPlay(void*) { - LLUICtrl* control = eventIn.getControl (); - - LLParcel* parcel = gParcelMgr->getAgentParcel(); - if ( control == mMusicRemote ) + if (!gOverlayBar) { - if (gAudiop) + return; + } + gOverlayBar->mMusicState = PLAYING; // desired state + if (gAudiop) + { + LLParcel* parcel = gParcelMgr->getAgentParcel(); + if ( parcel ) { - if ( parcel ) + // this doesn't work properly when crossing parcel boundaries - even when the + // stream is stopped, it doesn't return the right thing - commenting out for now. +// if ( gAudiop->isInternetStreamPlaying() == 0 ) { - // this doesn't work properly when crossing parcel boundaries - even when the - // stream is stopped, it doesn't return the right thing - commenting out for now. - //if ( gAudiop->isInternetStreamPlaying() == 0 ) - //{ - const char* music_url = parcel->getMusicURL(); - - gAudiop->startInternetStream(music_url); - - mMusicRemote->setTransportState ( LLMediaRemoteCtrl::Play, FALSE ); - //} + gAudiop->startInternetStream(parcel->getMusicURL()); } - }; - - // CP: this is the old way of doing things (click play each time on a parcel to start stream) - //if (gAudiop) - //{ - // if (gAudiop->isInternetStreamPlaying() > 0) - // { - // gAudiop->pauseInternetStream ( 0 ); - // } - // else - // { - // if (parcel) - // { - // const char* music_url = parcel->getMusicURL(); - // gAudiop->startInternetStream(music_url); - // } - // } - //}; - //mMusicRemote->setTransportState ( LLMediaRemoteCtrl::Stop, FALSE ); + } } - else - if ( control == mMediaRemote ) +} +//static +void LLOverlayBar::musicPause(void*) +{ + if (!gOverlayBar) { - LLParcel* parcel = gParcelMgr->getAgentParcel(); - if (parcel) + return; + } + gOverlayBar->mMusicState = PAUSED; // desired state + if (gAudiop) + { + gAudiop->pauseInternetStream(1); + } +} +//static +void LLOverlayBar::musicStop(void*) +{ + if (!gOverlayBar) + { + return; + } + gOverlayBar->mMusicState = STOPPED; // desired state + if (gAudiop) + { + gAudiop->stopInternetStream(); + } +} + +//static +void LLOverlayBar::enableMusicButtons(LLPanel* panel) +{ + BOOL play_enabled = FALSE; + BOOL play_visible = TRUE; + BOOL pause_visible = FALSE; + BOOL stop_enabled = FALSE; + if ( gAudiop && gOverlayBar && gSavedSettings.getBOOL("AudioStreamingMusic")) + { + play_enabled = TRUE; + S32 is_playing = gAudiop->isInternetStreamPlaying(); + if (is_playing == 1) { - LLString path( "" ); - LLMediaEngine::getInstance ()->convertImageAndLoadUrl( true, false, path ); - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Play, TRUE ); + play_visible = FALSE; + pause_visible = TRUE; + stop_enabled = TRUE; } - }; + else if (is_playing == 2) + { + play_visible = TRUE; + pause_visible = FALSE; + stop_enabled = TRUE; + } + } + panel->childSetEnabled("music_play", play_enabled); + panel->childSetEnabled("music_pause", play_enabled); + panel->childSetVisible("music_play", play_visible); + panel->childSetVisible("music_pause", pause_visible); + panel->childSetEnabled("music_stop", stop_enabled); } -//////////////////////////////////////////////////////////////////////////////// -// -// -void LLOverlayBar::onPauseButtonPressed( const LLMediaRemoteCtrlObserver::EventType& eventIn ) +//static +void LLOverlayBar::enableMediaButtons(LLPanel* panel) { - LLUICtrl* control = eventIn.getControl (); + // Media + BOOL play_enabled = FALSE; + BOOL play_visible = TRUE; + BOOL pause_visible = FALSE; + BOOL stop_enabled = FALSE; - if ( control == mMusicRemote ) + if ( LLMediaEngine::getInstance() && gOverlayBar && gSavedSettings.getBOOL("AudioStreamingVideo") ) { - if (gAudiop) + play_enabled = TRUE; + if (LLMediaEngine::getInstance()->getMediaRenderer()) { - gAudiop->pauseInternetStream ( 1 ); - }; - mMusicRemote->setTransportState ( LLMediaRemoteCtrl::Play, FALSE ); + if ( LLMediaEngine::getInstance()->getMediaRenderer()->isPlaying() || + LLMediaEngine::getInstance()->getMediaRenderer()->isLooping() ) + { + play_visible = FALSE; + pause_visible = TRUE; + stop_enabled = TRUE; + } + else if ( LLMediaEngine::getInstance()->getMediaRenderer()->isPaused() ) + { + play_visible = TRUE; + pause_visible = FALSE; + stop_enabled = TRUE; + } + } } - else - if ( control == mMediaRemote ) - { - LLMediaEngine::getInstance ()->pause (); - mMediaRemote->setTransportState ( LLMediaRemoteCtrl::Pause, TRUE ); - }; + panel->childSetEnabled("media_play", play_enabled); + panel->childSetEnabled("media_pause", play_enabled); + panel->childSetVisible("media_play", play_visible); + panel->childSetVisible("media_pause", pause_visible); + panel->childSetEnabled("media_stop", stop_enabled); +} + +void LLOverlayBar::toggleAudioVolumeFloater(void* user_data) +{ + LLFloaterAudioVolume::toggleInstance(LLSD()); } diff --git a/linden/indra/newview/lloverlaybar.h b/linden/indra/newview/lloverlaybar.h index 1f15023..de6c0ae 100644 --- a/linden/indra/newview/lloverlaybar.h +++ b/linden/indra/newview/lloverlaybar.h @@ -45,11 +45,10 @@ class LLUUID; class LLFrameTimer; class LLStatGraph; class LLSlider; -class LLVolumeSliderCtrl; +class LLVoiceRemoteCtrl; class LLOverlayBar -: public LLPanel, - public LLMediaRemoteCtrlObserver +: public LLPanel { public: LLOverlayBar(const std::string& name, const LLRect& rect ); @@ -58,14 +57,16 @@ public: virtual EWidgetType getWidgetType() const; virtual LLString getWidgetTag() const; - virtual void reshape(S32 width, S32 height, BOOL called_from_parent); - - void refresh(); + /*virtual*/ void refresh(); + /*virtual*/ void draw(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); void layoutButtons(); - /*virtual*/ void draw(); - + // helpers for returning desired state + BOOL mediaPlaying() { return mMediaState == PLAYING; } + BOOL musicPlaying() { return mMusicState == PLAYING; } + static void onClickIMReceived(void* data); static void onClickSetNotBusy(void* data); static void onClickReleaseKeys(void* data); @@ -73,23 +74,35 @@ public: static void onClickStandUp(void* data); static void onClickResetView(void* data); - // observer overrides - void onVolumeChange ( const LLMediaRemoteCtrlObserver::EventType& eventIn ); - void onStopButtonPressed ( const LLMediaRemoteCtrlObserver::EventType& eventIn ); - void onPlayButtonPressed ( const LLMediaRemoteCtrlObserver::EventType& eventIn ); - void onPauseButtonPressed ( const LLMediaRemoteCtrlObserver::EventType& eventIn ); - - LLMediaRemoteCtrl* getMusicRemoteControl () { return mMusicRemote; }; + //static media helper functions + static void mediaPlay(void*); + static void mediaPause(void*); + static void mediaStop(void*); + + static void musicPlay(void*); + static void musicPause(void*); + static void musicStop(void*); -protected: + static void toggleAudioVolumeFloater(void*); + + static void enableMediaButtons(LLPanel* panel); + static void enableMusicButtons(LLPanel* panel); +protected: + static void* createMasterRemote(void* userdata); static void* createMusicRemote(void* userdata); static void* createMediaRemote(void* userdata); + static void* createVoiceRemote(void* userdata); protected: + LLMediaRemoteCtrl* mMasterRemote; LLMediaRemoteCtrl* mMusicRemote; LLMediaRemoteCtrl* mMediaRemote; + LLVoiceRemoteCtrl* mVoiceRemote; BOOL isBuilt; + enum { STOPPED=0, PLAYING=1, PAUSED=2 }; + BOOL mMediaState; + BOOL mMusicState; }; extern LLOverlayBar* gOverlayBar; diff --git a/linden/indra/newview/llpanelaudioprefs.cpp b/linden/indra/newview/llpanelaudioprefs.cpp index 4a58cea..b28fb83 100644 --- a/linden/indra/newview/llpanelaudioprefs.cpp +++ b/linden/indra/newview/llpanelaudioprefs.cpp @@ -38,70 +38,58 @@ #include "llfontgl.h" // project includes -#include "llviewerwindow.h" -#include "llui.h" -#include "llspinctrl.h" -#include "llslider.h" -#include "llradiogroup.h" -#include "llsliderctrl.h" -#include "llcheckboxctrl.h" -#include "lltextbox.h" +#include "audioengine.h" #include "llbutton.h" +#include "llcheckboxctrl.h" #include "llcombobox.h" -#include "audioengine.h" -#include "llmediaengine.h" #include "llfirstuse.h" +#include "llmediaengine.h" +#include "llnotify.h" +#include "llpanelaudiovolume.h" #include "llparcel.h" +#include "llradiogroup.h" +#include "llresmgr.h" +#include "llslider.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltextbox.h" +#include "llui.h" #include "llviewerparcelmgr.h" -#include "llnotify.h" #include "llvieweruictrlfactory.h" -#include "llresmgr.h" +#include "llviewerwindow.h" #include "viewer.h" // do_disconnect // -// Imported globals -// - -extern LLAudioEngine *gAudiop; - -// -// Globals -// - - -// // Static functions // - - +//static +void* LLPanelAudioPrefs::createVolumePanel(void* data) +{ + LLPanelAudioVolume* panel = new LLPanelAudioVolume(); + return panel; +} LLPanelAudioPrefs::LLPanelAudioPrefs() { - - gUICtrlFactory->buildPanel(this, "panel_preferences_audio.xml"); - - + mFactoryMap["Volume Panel"] = LLCallbackMap(createVolumePanel, NULL); + + gUICtrlFactory->buildPanel(this, "panel_preferences_audio.xml", &getFactoryMap()); } - LLPanelAudioPrefs::~LLPanelAudioPrefs() { // Children all cleaned up by default view destructor. } - - - BOOL LLPanelAudioPrefs::postBuild() { - - - mPreviousMediaVolume = gSavedSettings.getF32("MediaAudioVolume"); mPreviousVolume = gSavedSettings.getF32("AudioLevelMaster"); + mPreviousSFX = gSavedSettings.getF32("AudioLevelSFX"); mPreviousUI = gSavedSettings.getF32("AudioLevelUI"); - mPreviousFootsteps = gSavedSettings.getF32("AudioLevelFootsteps"); - mPreviousWind = gSavedSettings.getF32("AudioLevelWind"); + mPreviousEnvironment = gSavedSettings.getF32("AudioLevelAmbient"); + mPreviousMusicVolume = gSavedSettings.getF32("AudioLevelMusic"); + mPreviousMediaVolume = gSavedSettings.getF32("AudioLevelMedia"); mPreviousDoppler = gSavedSettings.getF32("AudioLevelDoppler"); mPreviousDistance = gSavedSettings.getF32("AudioLevelDistance"); mPreviousRolloff = gSavedSettings.getF32("AudioLevelRolloff"); @@ -117,87 +105,20 @@ BOOL LLPanelAudioPrefs::postBuild() mPreviousMuteAudio = gSavedSettings.getBOOL("MuteAudio"); mPreviousMuteWhenMinimized = gSavedSettings.getBOOL("MuteWhenMinimized"); - - - childSetCommitCallback("disable audio", onMuteAudio, this); - - enable(!gSavedSettings.getBOOL("MuteAudio")); - return TRUE; } - -void LLPanelAudioPrefs::enable(BOOL b) -{ - childSetEnabled("mute_when_minimized", b); - - childSetEnabled("streaming_text", b); - childSetEnabled("streaming_music", b); - childSetEnabled("streaming_video", b); - - childSetEnabled("System Volume", b); - childSetEnabled("system_volume_text", b); - - childSetEnabled("Wind Volume", b); - childSetEnabled("wind_volume_text", b); - - childSetEnabled("Footsteps Volume", b); - childSetEnabled("footsteps_volume_text", b); - - childSetEnabled("UI Volume", b); - childSetEnabled("ui_volume", b); - - childSetEnabled("Doppler Effect", b); - childSetEnabled("doppler_effect_text", b); - - childSetEnabled("Distance Factor", b); - childSetEnabled("distance_factor_text", b); - - childSetEnabled("Rolloff Factor", b); - childSetEnabled("rolloff_factor_text", b); - - childSetEnabled("L$ Change Threshold", b); - - childSetEnabled("Health Change Threshold", b); - - childSetEnabled("bitrate", b); - childSetEnabled("default_upload_bitrate_text", b); -} - -struct LLPARestartData -{ - BOOL mMuteAudio; -}; - - - -void LLPanelAudioPrefs::apply() -{ - -} - - - -void LLPanelAudioPrefs::onMuteAudio(LLUICtrl* ctrl, void* userdata) -{ - LLPanelAudioPrefs* self = (LLPanelAudioPrefs*)userdata; - LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)ctrl; - - self->enable(!check->get()); - -} - - void LLPanelAudioPrefs::cancel() { gSavedSettings.setS32("AudioDefaultBitrate", mPreviousBitrate); - gSavedSettings.setF32("MediaAudioVolume", mPreviousMediaVolume); gSavedSettings.setF32("AudioLevelMaster", mPreviousVolume ); gSavedSettings.setF32("AudioLevelUI", mPreviousUI ); - gSavedSettings.setF32("AudioLevelFootsteps", mPreviousFootsteps ); - gSavedSettings.setF32("AudioLevelWind", mPreviousWind ); + gSavedSettings.setF32("AudioLevelSFX", mPreviousSFX ); + gSavedSettings.setF32("AudioLevelAmbient", mPreviousEnvironment ); + gSavedSettings.setF32("AudioLevelMusic", mPreviousMusicVolume); + gSavedSettings.setF32("AudioLevelMedia", mPreviousMediaVolume); gSavedSettings.setF32("AudioLevelDoppler", mPreviousDoppler ); gSavedSettings.setF32("AudioLevelDistance", mPreviousDistance ); gSavedSettings.setF32("AudioLevelRolloff", mPreviousRolloff ); @@ -211,7 +132,4 @@ void LLPanelAudioPrefs::cancel() gSavedSettings.setBOOL("MuteAudio", mPreviousMuteAudio ); gSavedSettings.setBOOL("MuteWhenMinimized", mPreviousMuteWhenMinimized ); - - - } diff --git a/linden/indra/newview/llpanelaudioprefs.h b/linden/indra/newview/llpanelaudioprefs.h index 63ac77b..9fd4e8d 100644 --- a/linden/indra/newview/llpanelaudioprefs.h +++ b/linden/indra/newview/llpanelaudioprefs.h @@ -43,24 +43,21 @@ class LLPanelAudioPrefs : public LLPanel public: LLPanelAudioPrefs(); virtual ~LLPanelAudioPrefs(); - - void apply(); // Apply the changed values. + void cancel(); // Cancel the changed values. - void enable(BOOL b); virtual BOOL postBuild(); - - static void restartCallback(S32 option, void *userdata); - static void onMuteAudio(LLUICtrl* ctrl, void* userdata); + static void* createVolumePanel(void* data); + protected: - F32 mPreviousVolume; + F32 mPreviousMusicVolume; F32 mPreviousMediaVolume; + F32 mPreviousSFX; F32 mPreviousUI; - F32 mPreviousFootsteps; - F32 mPreviousWind; + F32 mPreviousEnvironment; F32 mPreviousDoppler; F32 mPreviousDistance; F32 mPreviousRolloff; diff --git a/linden/indra/newview/llpanelaudiovolume.cpp b/linden/indra/newview/llpanelaudiovolume.cpp new file mode 100644 index 0000000..902614e --- /dev/null +++ b/linden/indra/newview/llpanelaudiovolume.cpp @@ -0,0 +1,109 @@ +/** + * @file llpanelaudiovolume.cpp + * @brief A remote control for media (video and music) + * + * Copyright (c) 2005-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelaudiovolume.h" + +#include "lloverlaybar.h" +#include "llviewercontrol.h" +#include "llvieweruictrlfactory.h" + +//////////////////////////////////////////////////////////////////////////////// +// Floater version of audio panel +// + +//static +void* LLFloaterAudioVolume::createVolumePanel(void* data) +{ + LLPanelAudioVolume* panel = new LLPanelAudioVolume(); + return panel; +} + +LLFloaterAudioVolume::LLFloaterAudioVolume(const LLSD& seed) +{ + mFactoryMap["Volume Panel"] = LLCallbackMap(createVolumePanel, NULL); + gUICtrlFactory->buildFloater(this, "floater_audio_volume.xml", &getFactoryMap()); + + S32 pos_x = mRect.mLeft; + S32 pos_y = mRect.mBottom; + LLView* volume_panel_view = gOverlayBar->getChildByName("master_volume"); + if (volume_panel_view) + { + pos_x = volume_panel_view->getRect().mLeft; + pos_y = volume_panel_view->getRect().mTop; + } + + setOrigin(pos_x, pos_y); + gFloaterView->adjustToFitScreen(this, FALSE); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// +LLPanelAudioVolume::LLPanelAudioVolume() +{ +} + +BOOL LLPanelAudioVolume::postBuild() +{ + childSetAction("media_play",LLOverlayBar::mediaPlay,this); + childSetAction("media_stop",LLOverlayBar::mediaStop,this); + childSetAction("media_pause",LLOverlayBar::mediaPause,this); + + childSetAction("music_play",LLOverlayBar::musicPlay,this); + childSetAction("music_stop",LLOverlayBar::musicStop,this); + childSetAction("music_pause",LLOverlayBar::musicPause,this); + + return TRUE; +} + +LLPanelAudioVolume::~LLPanelAudioVolume () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +// +void LLPanelAudioVolume::draw() +{ + LLOverlayBar::enableMusicButtons(this); + LLOverlayBar::enableMediaButtons(this); + BOOL mute = gSavedSettings.getBOOL("MuteAudio"); + bool enable = mute ? false : true; + childSetEnabled("System Volume", enable); + childSetEnabled("Music Volume", enable); + childSetEnabled("Media Volume", enable); + childSetEnabled("Voice Volume", enable); + childSetEnabled("SFX Volume", enable); + childSetEnabled("UI Volume", enable); + childSetEnabled("Wind Volume", enable); + childSetEnabled("Footsteps Volume", enable); + LLPanel::draw(); +} + diff --git a/linden/indra/newview/llpanelaudiovolume.h b/linden/indra/newview/llpanelaudiovolume.h new file mode 100644 index 0000000..8a824d2 --- /dev/null +++ b/linden/indra/newview/llpanelaudiovolume.h @@ -0,0 +1,55 @@ +/** + * @file llpanelaudiovolume.h + * @brief Audio preference definitions + * + * Copyright (c) 2001-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LL_LLPANELAUDIOVOLUME_H +#define LL_LLPANELAUDIOVOLUME_H + +#include "llpanel.h" +#include "llfloater.h" + +class LLFloaterAudioVolume : + public LLUISingleton, + public LLFloater +{ + friend class LLUISingleton; +public: + LLFloaterAudioVolume(const LLSD& seed); + static void* createVolumePanel(void* data); +}; + +class LLPanelAudioVolume : public LLPanel +{ +public: + LLPanelAudioVolume(); + virtual ~LLPanelAudioVolume(); + + virtual BOOL postBuild(); + virtual void draw(); +}; + +#endif diff --git a/linden/indra/newview/llpanelavatar.cpp b/linden/indra/newview/llpanelavatar.cpp index 0180bb3..b79993f 100644 --- a/linden/indra/newview/llpanelavatar.cpp +++ b/linden/indra/newview/llpanelavatar.cpp @@ -91,6 +91,7 @@ BOOL LLPanelAvatar::sAllowFirstLife = FALSE; // RN: move these to lldbstrings.h static const S32 DB_USER_FAVORITES_STR_LEN = 254; +const char LOADING_MSG[] = "Loading..."; static const char IM_DISABLED_TOOLTIP[] = "Instant Message (IM).\nDisabled because you do not have their card."; static const char IM_ENABLED_TOOLTIP[] = "Instant Message (IM)"; static const S32 LEFT = HPAD; @@ -830,7 +831,7 @@ void LLPanelAvatarNotes::refresh() void LLPanelAvatarNotes::clearControls() { - childSetText("notes edit", "Loading..."); + childSetText("notes edit", LOADING_MSG); childSetEnabled("notes edit", false); } @@ -1271,6 +1272,8 @@ LLPanelAvatar::LLPanelAvatar( mAvatarID( LLUUID::null ), // mAvatarID is set with 'setAvatar' or 'setAvatarID' mHaveProperties(FALSE), mHaveStatistics(FALSE), + mHaveNotes(false), + mLastNotes(), mAllowEdit(allow_edit) { @@ -1415,6 +1418,7 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, setOnlineStatus(online_status); BOOL own_avatar = (mAvatarID == gAgent.getID() ); + BOOL avatar_is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; mPanelSecondLife->enableControls(own_avatar && mAllowEdit); mPanelWeb->enableControls(own_avatar && mAllowEdit); @@ -1460,6 +1464,8 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, mPanelNotes->clearControls(); mPanelNotes->setDataRequested(false); + mHaveNotes = false; + mLastNotes.clear(); // Request just the first two pages of data. The picks, // classifieds, and notes will be requested when that panel @@ -1471,8 +1477,8 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, if (mAllowEdit) { // OK button disabled until properties data arrives - childSetVisible("OK",TRUE); - childSetEnabled("OK",TRUE); + childSetVisible("OK", true); + childSetEnabled("OK", false); childSetVisible("Cancel",TRUE); childSetEnabled("Cancel",TRUE); } @@ -1530,7 +1536,7 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, childSetToolTip("Show on Map",childGetValue("ShowOnMapFriendOnline").asString()); } childSetVisible("Add Friend...", true); - childSetEnabled("Add Friend...", true); + childSetEnabled("Add Friend...", !avatar_is_friend); childSetVisible("Pay...",TRUE); childSetEnabled("Pay...",FALSE); } @@ -1604,12 +1610,12 @@ void LLPanelAvatar::resetGroupList() void LLPanelAvatar::onClickIM(void* userdata) { LLPanelAvatar* self = (LLPanelAvatar*) userdata; - gIMView->setFloaterOpen(TRUE); + gIMMgr->setFloaterOpen(TRUE); std::string name; LLNameEditor* nameedit = LLViewerUICtrlFactory::getNameEditorByName(self->mPanelSecondLife, "name"); if (nameedit) name = nameedit->getText(); - gIMView->addSession(name, IM_NOTHING_SPECIAL, self->mAvatarID); + gIMMgr->addSession(name, IM_NOTHING_SPECIAL, self->mAvatarID); } @@ -1639,7 +1645,7 @@ void LLPanelAvatar::onClickAddFriend(void* userdata) LLNameEditor* name_edit = LLViewerUICtrlFactory::getNameEditorByName(self->mPanelSecondLife, "name"); if (name_edit) { - LLFloaterFriends::requestFriendshipDialog(self->getAvatarID(), + LLPanelFriends::requestFriendshipDialog(self->getAvatarID(), name_edit->getText()); } } @@ -1767,7 +1773,19 @@ void LLPanelAvatar::sendAvatarPropertiesRequest() void LLPanelAvatar::sendAvatarNotesUpdate() { std::string notes = mPanelNotes->childGetValue("notes edit").asString(); - + + if (!mHaveNotes + && (notes.empty() || notes == LOADING_MSG)) + { + // no notes from server and no user updates + return; + } + if (notes == mLastNotes) + { + // Avatar notes unchanged + return; + } + LLMessageSystem *msg = gMessageSystem; msg->newMessage("AvatarNotesUpdate"); @@ -2175,6 +2193,8 @@ void LLPanelAvatar::processAvatarNotesReply(LLMessageSystem *msg, void**) msg->getString("Data", "Notes", DB_USER_NOTE_SIZE, text); self->childSetValue("notes edit", text); self->childSetEnabled("notes edit", true); + self->mHaveNotes = true; + self->mLastNotes = text; } } diff --git a/linden/indra/newview/llpanelavatar.h b/linden/indra/newview/llpanelavatar.h index b3b4e72..05b18c5 100644 --- a/linden/indra/newview/llpanelavatar.h +++ b/linden/indra/newview/llpanelavatar.h @@ -323,16 +323,15 @@ public: static void onClickCSR( void *userdata); static void onClickMute( void *userdata); +private: + void enableOKIfReady(); + static void finishKick(S32 option, const LLString& text, void* userdata); static void finishFreeze(S32 option, const LLString& text, void* userdata); static void finishUnfreeze(S32 option, const LLString& text, void* userdata); static void showProfileCallback(S32 option, void *userdata); - // Teen users are not allowed to see or enter data into the first life page, - // or their own about/interests text entry fields. - static BOOL sAllowFirstLife; - static void* createPanelAvatar(void* data); static void* createFloaterAvatarInfo(void* data); static void* createPanelAvatarSecondLife(void* data); @@ -353,13 +352,20 @@ public: LLPanelAvatarWeb* mPanelWeb; LLDropTarget* mDropTarget; + + // Teen users are not allowed to see or enter data into the first life page, + // or their own about/interests text entry fields. + static BOOL sAllowFirstLife; -protected: - void enableOKIfReady(); +private: LLUUID mAvatarID; // for which avatar is this window? BOOL mIsFriend; // Are we friends? BOOL mHaveProperties; BOOL mHaveStatistics; + // only update note if data received from database and + // note is changed from database version + bool mHaveNotes; + std::string mLastNotes; LLTabContainerCommon* mTab; BOOL mAllowEdit; diff --git a/linden/indra/newview/llpanelclassified.cpp b/linden/indra/newview/llpanelclassified.cpp index 408f91a..f7ef441 100644 --- a/linden/indra/newview/llpanelclassified.cpp +++ b/linden/indra/newview/llpanelclassified.cpp @@ -105,20 +105,20 @@ LLPanelClassified::LLPanelClassified(BOOL in_finder) mPriceForListing(0), mDataRequested(FALSE), mPaidFor(FALSE), - mPosGlobal(), - mSnapshotCtrl(NULL), - mNameEditor(NULL), - mDescEditor(NULL), - mLocationEditor(NULL), + mPosGlobal(), + mSnapshotCtrl(NULL), + mNameEditor(NULL), + mDescEditor(NULL), + mLocationEditor(NULL), mCategoryCombo(NULL), + mMatureCheck(NULL), + mAutoRenewCheck(NULL), mUpdateBtn(NULL), - mTeleportBtn(NULL), - mMapBtn(NULL), + mTeleportBtn(NULL), + mMapBtn(NULL), mProfileBtn(NULL), mInfoText(NULL), - mMatureCheck(NULL), - mAutoRenewCheck(NULL), - mSetBtn(NULL), + mSetBtn(NULL), mClickThroughText(NULL) { sAllPanels.push_back(this); @@ -845,6 +845,7 @@ void LLPanelClassified::onCommitAny(LLUICtrl* ctrl, void* data) void LLPanelClassified::onFocusReceived(LLUICtrl* ctrl, void* data) { // allow the data to be saved + // Dave/Simon TODO: replace this with better isDirty() functionality onCommitAny(ctrl, data); } diff --git a/linden/indra/newview/llpanelclassified.h b/linden/indra/newview/llpanelclassified.h index 0ebac2c..6f5e370 100644 --- a/linden/indra/newview/llpanelclassified.h +++ b/linden/indra/newview/llpanelclassified.h @@ -115,8 +115,8 @@ protected: BOOL mInFinder; bool mDirty; bool mForceClose; - LLUUID mClassifiedID; - LLUUID mRequestedID; + LLUUID mClassifiedID; + LLUUID mRequestedID; LLUUID mCreatorID; LLUUID mParcelID; S32 mPriceForListing; @@ -129,24 +129,25 @@ protected: BOOL mPaidFor; LLString mSimName; - LLVector3d mPosGlobal; + LLVector3d mPosGlobal; - LLTextureCtrl* mSnapshotCtrl; - LLLineEditor* mNameEditor; + // Values the user may change + LLTextureCtrl* mSnapshotCtrl; + LLLineEditor* mNameEditor; LLLineEditor* mDateEditor; - LLTextEditor* mDescEditor; - LLLineEditor* mLocationEditor; + LLTextEditor* mDescEditor; + LLLineEditor* mLocationEditor; LLComboBox* mCategoryCombo; + LLCheckBoxCtrl* mMatureCheck; + LLCheckBoxCtrl* mAutoRenewCheck; LLButton* mUpdateBtn; - LLButton* mTeleportBtn; - LLButton* mMapBtn; + LLButton* mTeleportBtn; + LLButton* mMapBtn; LLButton* mProfileBtn; LLTextBox* mInfoText; - LLCheckBoxCtrl* mMatureCheck; - LLCheckBoxCtrl* mAutoRenewCheck; - LLButton* mSetBtn; + LLButton* mSetBtn; LLTextBox* mClickThroughText; LLRect mSnapshotSize; diff --git a/linden/indra/newview/llpaneldebug.cpp b/linden/indra/newview/llpaneldebug.cpp index 3166a1d..0293c24 100644 --- a/linden/indra/newview/llpaneldebug.cpp +++ b/linden/indra/newview/llpaneldebug.cpp @@ -100,6 +100,7 @@ LLPanelDebug::LLPanelDebug(const std::string& name, const LLRect& rect) RULER2 + SPINCTRL_DEFAULT_LABEL_WIDTH + SPINCTRL_BTN_WIDTH, TRUE, TRUE, + FALSE, NULL, NULL, (F32)gSavedSettings.getS32("DropShadowFloater"), 0.f, 10.f, 1.0f, @@ -118,6 +119,7 @@ LLPanelDebug::LLPanelDebug(const std::string& name, const LLRect& rect) RULER2 + SPINCTRL_DEFAULT_LABEL_WIDTH + SPINCTRL_BTN_WIDTH, TRUE, TRUE, + FALSE, NULL, NULL, (F32)gSavedSettings.getS32("DropShadowButton"), 0.f, 10.f, 1.0f, diff --git a/linden/indra/newview/llpaneldirbrowser.cpp b/linden/indra/newview/llpaneldirbrowser.cpp index 52bd0f7..232ee35 100644 --- a/linden/indra/newview/llpaneldirbrowser.cpp +++ b/linden/indra/newview/llpaneldirbrowser.cpp @@ -1254,9 +1254,10 @@ void LLPanelDirBrowser::onKeystrokeName(LLLineEditor* line, void* data) } } -void LLPanelDirBrowser::onVisibilityChange(BOOL curVisibilityIn) +// setup results when shown +void LLPanelDirBrowser::onVisibilityChange(BOOL new_visibility) { - if (curVisibilityIn) + if (new_visibility) { onCommitList(NULL, this); } diff --git a/linden/indra/newview/llpaneldisplay.cpp b/linden/indra/newview/llpaneldisplay.cpp index d79dcb4..c4fa1dc 100644 --- a/linden/indra/newview/llpaneldisplay.cpp +++ b/linden/indra/newview/llpaneldisplay.cpp @@ -520,6 +520,7 @@ void LLPanelDisplay2::refreshEnabledState() void LLPanelDisplay2::apply() { + // Anisotropic rendering BOOL old_anisotropic = LLImageGL::sGlobalUseAnisotropic; LLImageGL::sGlobalUseAnisotropic = childGetValue("ani"); diff --git a/linden/indra/newview/llpanelgeneral.cpp b/linden/indra/newview/llpanelgeneral.cpp index 10aef2c..7d1c778 100644 --- a/linden/indra/newview/llpanelgeneral.cpp +++ b/linden/indra/newview/llpanelgeneral.cpp @@ -58,8 +58,6 @@ // Imported globals // -extern F32 gAFKTimeout; - void set_crash_behavior(LLUICtrl* ctrl, void* data); void set_start_location(LLUICtrl* ctrl, void* data); diff --git a/linden/indra/newview/llpanelgroup.cpp b/linden/indra/newview/llpanelgroup.cpp index 8061e42..5887cc0 100644 --- a/linden/indra/newview/llpanelgroup.cpp +++ b/linden/indra/newview/llpanelgroup.cpp @@ -125,16 +125,7 @@ void LLPanelGroupTab::handleClickHelp() LLAlertDialog* dialogp = gViewerWindow->alertXml("GenericAlert", args); if (dialogp) { - LLView* viewp = this; - LLFloater* root_floater = NULL; - while(viewp) - { - if(viewp->getWidgetType() == WIDGET_TYPE_FLOATER) - { - root_floater = (LLFloater*)viewp; - } - viewp = viewp->getParent(); - } + LLFloater* root_floater = gFloaterView->getParentFloater(this);; if (root_floater) { root_floater->addDependentFloater(dialogp); diff --git a/linden/indra/newview/llpanelinventory.cpp b/linden/indra/newview/llpanelinventory.cpp index 13f07c0..a7dc298 100644 --- a/linden/indra/newview/llpanelinventory.cpp +++ b/linden/indra/newview/llpanelinventory.cpp @@ -604,7 +604,7 @@ void LLTaskInvFVBridge::performAction(LLFolderView* folder, LLInventoryModel* mo } else { - if (price > gStatusBar->getBalance()) + if (price > 0 && price > gStatusBar->getBalance()) { LLFloaterBuyCurrency::buyCurrency("This costs", price); } diff --git a/linden/indra/newview/llpanellogin.cpp b/linden/indra/newview/llpanellogin.cpp index fdc431c..7a0482b 100644 --- a/linden/indra/newview/llpanellogin.cpp +++ b/linden/indra/newview/llpanellogin.cpp @@ -44,6 +44,7 @@ #include "llcombobox.h" #include "llviewercontrol.h" #include "llfloaterabout.h" +#include "llfloatertest.h" #include "llfloaterpreference.h" #include "llfocusmgr.h" #include "lllineeditor.h" @@ -424,23 +425,30 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) return TRUE; } - #if LL_LIBXUL_ENABLED + if (('T' == key) && (MASK_CONTROL == mask)) + { + new LLFloaterSimple("floater_test.xml"); + return TRUE; + } + +#if LL_LIBXUL_ENABLED if ( KEY_F1 == key ) { llinfos << "Spawning HTML help window" << llendl; gViewerHtmlHelp.show(); return TRUE; - }; - #if ! LL_RELEASE_FOR_DOWNLOAD - if ( KEY_F2 == key ) - { - llinfos << "Spawning floater TOS window" << llendl; - LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,""); - tos_dialog->startModal(); - return TRUE; - }; - #endif - #endif + } + +# if !LL_RELEASE_FOR_DOWNLOAD + if ( KEY_F2 == key ) + { + llinfos << "Spawning floater TOS window" << llendl; + LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,""); + tos_dialog->startModal(); + return TRUE; + } +# endif +#endif if (!called_from_parent) { diff --git a/linden/indra/newview/llpanellogin.h b/linden/indra/newview/llpanellogin.h index 2133044..05590d3 100644 --- a/linden/indra/newview/llpanellogin.h +++ b/linden/indra/newview/llpanellogin.h @@ -35,6 +35,7 @@ #include "llmemory.h" #include "llviewerimage.h" #include "llstring.h" +#include "llmd5.h" class LLTextBox; class LLLineEditor; diff --git a/linden/indra/newview/llpanelpermissions.cpp b/linden/indra/newview/llpanelpermissions.cpp index 6e8a4ff..0cfef5c 100644 --- a/linden/indra/newview/llpanelpermissions.cpp +++ b/linden/indra/newview/llpanelpermissions.cpp @@ -807,14 +807,24 @@ void LLPanelPermissions::onClickOwner(void *data) void LLPanelPermissions::onClickGroup(void* data) { + LLPanelPermissions* panelp = (LLPanelPermissions*)data; LLUUID owner_id; LLString name; BOOL owners_identical = gSelectMgr->selectGetOwner(owner_id, name); + LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); + if(owners_identical && (owner_id == gAgent.getID())) { - LLFloaterGroups* fg; - fg = LLFloaterGroups::show(gAgent.getID(), LLFloaterGroups::CHOOSE_ONE); - fg->setOkCallback( cbGroupID, data ); + LLFloaterGroupPicker* fg; + fg = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); + fg->setSelectCallback( cbGroupID, data ); + + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg); + fg->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(fg); + } } } diff --git a/linden/indra/newview/llpolymesh.cpp b/linden/indra/newview/llpolymesh.cpp index 1edb8f5..6cc3fc7 100644 --- a/linden/indra/newview/llpolymesh.cpp +++ b/linden/indra/newview/llpolymesh.cpp @@ -278,7 +278,10 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) // Read a chunk //------------------------------------------------------------------------- char header[128]; /*Flawfinder: ignore*/ - fread(header, sizeof(char), 128, fp); + if (fread(header, sizeof(char), 128, fp) != 128) + { + llwarns << "Short read" << llendl; + } //------------------------------------------------------------------------- // Check for proper binary header diff --git a/linden/indra/newview/llprefschat.cpp b/linden/indra/newview/llprefschat.cpp index 70f7833..91cacd9 100644 --- a/linden/indra/newview/llprefschat.cpp +++ b/linden/indra/newview/llprefschat.cpp @@ -30,21 +30,8 @@ #include "llviewerprecompiledheaders.h" #include "llprefschat.h" - -#include "llcheckboxctrl.h" -#include "llcolorswatch.h" -#include "llpanel.h" -#include "llradiogroup.h" - -#include "llchatbar.h" -#include "llconsole.h" -#include "llspinctrl.h" -#include "llsliderctrl.h" #include "llviewercontrol.h" #include "llvieweruictrlfactory.h" -#include "message.h" -#include "viewer.h" -#include "lltexteditor.h" class LLPrefsChatImpl : public LLPanel { diff --git a/linden/indra/newview/llprefsvoice.cpp b/linden/indra/newview/llprefsvoice.cpp new file mode 100644 index 0000000..c66a3d0 --- /dev/null +++ b/linden/indra/newview/llprefsvoice.cpp @@ -0,0 +1,277 @@ +/** + * @file llprefsvoice.cpp + * @author Richard Nelson + * @brief Voice chat preferences panel + * + * Copyright (c) 2003-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llprefsvoice.h" + +#include "llcheckboxctrl.h" +#include "llcombobox.h" + +#include "llviewercontrol.h" +#include "llvieweruictrlfactory.h" + +#include "llmodaldialog.h" +#include "llkeyboard.h" +#include "llfocusmgr.h" +#include "llfloatervoicewizard.h" + +#include "viewer.h" + +#include "llvoiceclient.h" + +class LLVoiceHotkeySelectDialog : public LLModalDialog +{ +private: + LLPrefsVoiceLogic *mParent; + LLFloater *mOldFrontmost; + +public: + LLVoiceHotkeySelectDialog( LLPrefsVoiceLogic *parent ) + : LLModalDialog( "", 240, 100 ), + mParent( parent ) + { + mOldFrontmost = gFloaterView->getFrontmost(); + + gUICtrlFactory->buildFloater(this, "floater_select_key.xml"); + + childSetAction("Cancel", LLVoiceHotkeySelectDialog::onCancel, this ); + childSetFocus("Cancel"); + } + + /*virtual*/ void setFocus( BOOL b ) + { + LLFloater::setFocus(b); + + // This forces keyboard processing to happen at the raw key level instead of going through handleUnicodeChar. + gFocusMgr.removeKeyboardFocusWithoutCallback(gFocusMgr.getKeyboardFocus()); + } + + static void onCancel( void* userdata ); + + BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent ); + +}; + +LLPrefsVoiceLogic::LLPrefsVoiceLogic(LLPanel* panelp) : + mPanel(panelp) +{ + init(); +} + +void LLPrefsVoiceLogic::init() +{ + mEnableVoice = gSavedSettings.getBOOL("EnableVoiceChat"); + + mVoiceCallsFriendsOnly = gSavedSettings.getBOOL("VoiceCallsFriendsOnly"); + mEnablePushToTalk = gSavedSettings.getBOOL("EnablePushToTalk"); + mModifier = gSavedSettings.getString("PushToTalkButton"); + mPushToTalkToggle = gSavedSettings.getBOOL("PushToTalkToggle"); + mEarLocation = gSavedSettings.getS32("VoiceEarLocation"); + + mCtrlEarLocation = LLUICtrlFactory::getSelectionInterfaceByName(mPanel, "ear_location"); + mCtrlEarLocation->selectByValue(LLSD(gSavedSettings.getS32("VoiceEarLocation"))); + mPanel->childSetCommitCallback("ear_location", onEarLocationCommit, this ); + + mPanel->childSetAction("launch_voice_wizard_button", onClickLaunchWizard, this); + mPanel->childSetAction("set_voice_hotkey_button", onClickSetKey, this); + mPanel->childSetAction("set_voice_middlemouse_button", onClickSetMiddleMouse, this); + + refresh(); + mEatNextSetKeyClick = FALSE; +} + +void LLPrefsVoiceLogic::refresh() +{ + mPanel->childSetVisible("voice_unavailable", gDisableVoice); + mPanel->childSetVisible("enable_voice_check", !gDisableVoice); + mPanel->childSetEnabled("enable_voice_check", !gDisableVoice); + + bool enable = !gDisableVoice && gSavedSettings.getBOOL("EnableVoiceChat"); + + mPanel->childSetEnabled("push_to_talk_check", enable); + mPanel->childSetEnabled("push_to_talk_label", enable); + mPanel->childSetEnabled("voice_call_friends_only_check", enable); + mPanel->childSetEnabled("push_to_talk_toggle_check", enable /*&& gSavedSettings.getBOOL("EnablePushToTalk")*/); + mPanel->childSetEnabled("ear_location", enable); + mPanel->childSetEnabled("set_voice_hotkey_button", enable /*&& gSavedSettings.getBOOL("EnablePushToTalk")*/); + mPanel->childSetEnabled("set_voice_middlemouse_button", enable /*&& gSavedSettings.getBOOL("EnablePushToTalk")*/); +} + +void LLPrefsVoiceLogic::cancel() +{ + gSavedSettings.setBOOL("EnableVoiceChat", mEnableVoice); + gSavedSettings.setBOOL("VoiceCallsFriendsOnly", mVoiceCallsFriendsOnly); + gSavedSettings.setBOOL("EnablePushToTalk", mEnablePushToTalk ); + gSavedSettings.setString("PushToTalkButton", mModifier); + gSavedSettings.setBOOL("PushToTalkToggle", mPushToTalkToggle ); + gSavedSettings.setS32("VoiceEarLocation", mEarLocation); +} + +void LLPrefsVoiceLogic::apply() +{ +} + +//static +void LLPrefsVoiceLogic::onEarLocationCommit(LLUICtrl* ctrl, void* user_data) +{ + LLCtrlSelectionInterface* interfacep = ctrl->getSelectionInterface(); + if (interfacep) + { + gSavedSettings.setS32("VoiceEarLocation", interfacep->getSimpleSelectedValue().asInteger()); + } +} + +//static +void LLPrefsVoiceLogic::onClickLaunchWizard(void* user_data) +{ + LLFloaterVoiceWizard::showInstance(); +} + +// static +void LLPrefsVoiceLogic::onClickSetKey(void* user_data) +{ + LLPrefsVoiceLogic* self=(LLPrefsVoiceLogic*)user_data; + if(self->mEatNextSetKeyClick) + { + self->mEatNextSetKeyClick = false; + } + else + { + LLVoiceHotkeySelectDialog* dialog = new LLVoiceHotkeySelectDialog( self ); + dialog->startModal(); + // dialog will delete itself + } +} + + +// static +void LLPrefsVoiceLogic::onClickSetMiddleMouse(void* user_data) +{ +// LLPrefsVoiceLogic* self=(LLPrefsVoiceLogic*)user_data; + + gSavedSettings.setString("PushToTalkButton", "MiddleMouse"); +} + +void LLPrefsVoiceLogic::setKey(KEY key, MASK mask) +{ + std::string keystring = LLKeyboard::stringFromKey(key); + gSavedSettings.setString("PushToTalkButton", keystring); + + if(key == ' ') + { + // This will cause the select dialog to immediately reopen. + // Eat the next click event. + mEatNextSetKeyClick = TRUE; + } +} + +void LLVoiceHotkeySelectDialog::onCancel( void* userdata ) +{ + LLVoiceHotkeySelectDialog* self = (LLVoiceHotkeySelectDialog*) userdata; + self->close(); // destroys this object + self->mOldFrontmost->setFrontmost(TRUE); +} + +BOOL LLVoiceHotkeySelectDialog::handleKey(KEY key, MASK mask, BOOL called_from_parent ) +{ + BOOL result = TRUE; + + // Suck up all keystokes except CTRL-Q. + BOOL is_quit = ('Q' == key) && (MASK_CONTROL == mask); + if(is_quit) + { + result = FALSE; + } + else + { + mParent->setKey(key, mask); + } + + close(); // destroys this object + mOldFrontmost->setFrontmost(TRUE); + + return result; +} + +//--------------------------------------------------------------------------- + + +LLPrefsVoice::LLPrefsVoice() +: LLPanel("Voice Chat Panel") +{ + gUICtrlFactory->buildPanel(this, "panel_preferences_voice.xml"); + mLogic = new LLPrefsVoiceLogic(this); + childSetAction("device_settings_btn", onClickDeviceSettingsBtn, this); + + // create floater immediately and keep it hidden + // since it stores preference state for audio devices + mDeviceSettings = LLFloaterDeviceSettings::getInstance(); + //*FIXME: getInstance() needs to not show the floater + LLFloaterDeviceSettings::hideInstance(); +} + +LLPrefsVoice::~LLPrefsVoice() +{ + delete mLogic; +} + +void LLPrefsVoice::draw() +{ + bool enable = !gDisableVoice && gSavedSettings.getBOOL("EnableVoiceChat"); + childSetEnabled("device_settings_btn", enable); + + mLogic->refresh(); + mDeviceSettings->refresh(); + LLPanel::draw(); +} + +void LLPrefsVoice::apply() +{ + mLogic->apply(); + mDeviceSettings->apply(); +} + +void LLPrefsVoice::cancel() +{ + mLogic->cancel(); + mDeviceSettings->cancel(); +} + +//static +void LLPrefsVoice::onClickDeviceSettingsBtn(void* user_data) +{ + LLPrefsVoice* prefs = (LLPrefsVoice*)user_data; + prefs->mDeviceSettings->open(); + LLFloater* parent_floater = gFloaterView->getParentFloater(prefs); + if (parent_floater) + { + parent_floater->addDependentFloater(prefs->mDeviceSettings, FALSE); + } +} diff --git a/linden/indra/newview/llprefsvoice.h b/linden/indra/newview/llprefsvoice.h new file mode 100644 index 0000000..e6b861d --- /dev/null +++ b/linden/indra/newview/llprefsvoice.h @@ -0,0 +1,87 @@ +/** + * @file llprefsvoice.h + * @brief Voice chat preferences panel + * + * Copyright (c) 2003-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LLPREFSVOICE_H +#define LLPREFSVOICE_H + +#include "llpanel.h" + +class LLFloaterDeviceSettings; + +class LLPrefsVoiceLogic +{ +public: + LLPrefsVoiceLogic(LLPanel* panelp); + virtual ~LLPrefsVoiceLogic(){}; + + virtual void init(); + + void apply(); + void cancel(); + void refresh(); + + void setKey(KEY key, MASK mask); + +protected: + + static void onClickSetKey(void* user_data); + static void onClickSetMiddleMouse(void* user_data); + static void onEarLocationCommit(LLUICtrl* ctrl, void* user_data); + static void onClickLaunchWizard(void* user_data); + + BOOL mEnableVoice; + BOOL mVoiceCallsFriendsOnly; + BOOL mEnablePushToTalk; + std::string mModifier; + BOOL mPushToTalkToggle; + S32 mEarLocation; + LLCtrlSelectionInterface *mCtrlEarLocation; + + BOOL mEatNextSetKeyClick; + + LLPanel* mPanel; +}; + +class LLPrefsVoice : public LLPanel +{ +public: + LLPrefsVoice(); + ~LLPrefsVoice(); + + /*virtual*/ void draw(); + void apply(); + void cancel(); + +protected: + static void onClickDeviceSettingsBtn(void* user_data); + + LLPrefsVoiceLogic* mLogic; + LLFloaterDeviceSettings* mDeviceSettings; +}; + +#endif // LLPREFSVOICE_H diff --git a/linden/indra/newview/llpreview.cpp b/linden/indra/newview/llpreview.cpp index 9b2d3f8..751a90f 100644 --- a/linden/indra/newview/llpreview.cpp +++ b/linden/indra/newview/llpreview.cpp @@ -62,7 +62,8 @@ LLPreview::LLPreview(const std::string& name) : mForceClose(FALSE), mUserResized(FALSE), mCloseAfterSave(FALSE), - mAssetStatus(PREVIEW_ASSET_UNLOADED) + mAssetStatus(PREVIEW_ASSET_UNLOADED), + mItem(NULL) { // don't add to instance list, since ItemID is null mAuxItem = new LLInventoryItem; // (LLPointer is auto-deleted) diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp index 9f3533e..a2ea141 100644 --- a/linden/indra/newview/llpreviewscript.cpp +++ b/linden/indra/newview/llpreviewscript.cpp @@ -1094,9 +1094,6 @@ LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, gUICtrlFactory->buildFloater(this,"floater_script_preview.xml", &factory_map); - moveResizeHandleToFront(); - - const LLInventoryItem* item = getItem(); childSetCommitCallback("desc", LLPreview::onText, this); @@ -1342,7 +1339,10 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, LLString line; while(!feof(fp)) { - fgets(buffer, MAX_STRING, fp); + if (fgets(buffer, MAX_STRING, fp) == NULL) + { + buffer[0] = '\0'; + } if(feof(fp)) { break; @@ -1617,8 +1617,6 @@ LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name, LLCallbackMap::map_t factory_map; factory_map["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); - moveResizeHandleToFront(); - gUICtrlFactory->buildFloater(this,"floater_live_lsleditor.xml", &factory_map); @@ -1849,12 +1847,16 @@ void LLLiveLSLEditor::loadScriptText(const char* filename) { // read in the whole file fseek(file, 0L, SEEK_END); - S32 file_length = ftell(file); + long file_length = ftell(file); fseek(file, 0L, SEEK_SET); char* buffer = new char[file_length+1]; - fread(buffer, file_length, 1, file); + size_t nread = fread(buffer, 1, file_length, file); + if (nread < (size_t) file_length) + { + llwarns << "Short read" << llendl; + } + buffer[nread] = '\0'; fclose(file); - buffer[file_length] = 0; mScriptEd->mEditor->setText(buffer); mScriptEd->mEditor->makePristine(); delete[] buffer; @@ -2049,6 +2051,13 @@ void LLLiveLSLEditor::saveIfNeeded() return; } LLString utf8text = mScriptEd->mEditor->getText(); + + // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 + if ( utf8text.size() == 0 ) + { + utf8text = " "; + } + fputs(utf8text.c_str(), fp); fclose(fp); fp = NULL; @@ -2118,7 +2127,10 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, while(!feof(fp)) { - fgets(buffer, MAX_STRING, fp); + if (fgets(buffer, MAX_STRING, fp) == NULL) + { + buffer[0] = '\0'; + } if(feof(fp)) { break; diff --git a/linden/indra/newview/llpreviewsound.cpp b/linden/indra/newview/llpreviewsound.cpp index 4e12cd0..7c7afe6 100644 --- a/linden/indra/newview/llpreviewsound.cpp +++ b/linden/indra/newview/llpreviewsound.cpp @@ -28,15 +28,16 @@ #include "llviewerprecompiledheaders.h" -#include "llpreviewsound.h" +#include "audioengine.h" +#include "llagent.h" // gAgent #include "llbutton.h" -#include "llresmgr.h" #include "llinventory.h" #include "llinventoryview.h" -#include "audioengine.h" -#include "llviewermessage.h" // send_guid_sound_trigger -#include "llagent.h" // gAgent #include "lllineeditor.h" +#include "llpreviewsound.h" +#include "llresmgr.h" +#include "llviewercontrol.h" +#include "llviewermessage.h" // send_guid_sound_trigger #include "llvieweruictrlfactory.h" extern LLAudioEngine* gAudiop; @@ -102,7 +103,7 @@ void LLPreviewSound::auditionSound( void *userdata ) if(item && gAudiop) { LLVector3d lpos_global = gAgent.getPositionGlobal(); - - gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), SOUND_GAIN, lpos_global); + F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); + gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), volume, lpos_global); } } diff --git a/linden/indra/newview/llpreviewtexture.cpp b/linden/indra/newview/llpreviewtexture.cpp index af727b9..5cba31d 100644 --- a/linden/indra/newview/llpreviewtexture.cpp +++ b/linden/indra/newview/llpreviewtexture.cpp @@ -435,7 +435,7 @@ void LLPreviewTexture::updateAspectRatio() S32 old_left = mRect.mLeft; if (getHost()) { - getHost()->growToFit(this, view_width, view_height); + getHost()->growToFit(view_width, view_height); } else { diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index 0cf8b00..ec01d54 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp @@ -547,7 +547,7 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) return object_found; } -void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim) +void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object) { // bail if nothing selected or if object wasn't selected in the first place if(!object) return; @@ -555,7 +555,30 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s // Collect all of the objects, and remove them LLDynamicArray objects; - object = (LLViewerObject*)object->getRoot(); + + if (include_entire_object) + { + // Since we're selecting a family, start at the root, but + // don't include an avatar. + LLViewerObject* root = object; + + while(!root->isAvatar() && root->getParent() && !root->isJointChild()) + { + LLViewerObject* parent = (LLViewerObject*)root->getParent(); + if (parent->isAvatar()) + { + break; + } + root = parent; + } + + object = root; + } + else + { + object = (LLViewerObject*)object->getRoot(); + } + object->addThisAndAllChildren(objects); remove(objects); @@ -3457,7 +3480,6 @@ void LLSelectMgr::deselectAll() mLastSentSelectionCenterGlobal.clearVec(); updatePointAt(); - gHUDManager->clearJoints(); updateSelectionCenter(); } @@ -5494,7 +5516,7 @@ void LLSelectMgr::updateSelectionCenter() // have stuff selected LLVector3d select_center; // keep a list of jointed objects for showing the joint HUDEffects - gHUDManager->clearJoints(); + LLDynamicArray < LLViewerObject *> jointed_objects; for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) @@ -5520,10 +5542,6 @@ void LLSelectMgr::updateSelectionCenter() mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); mSelectionBBox = bbox; - if (jointed_objects.count()) - { - gHUDManager->showJoints(&jointed_objects); - } } if ( !(gAgentID == LLUUID::null) && gToolMgr) @@ -5754,6 +5772,12 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) return TRUE; } +BOOL LLSelectMgr::setForceSelection(BOOL force) +{ + std::swap(mForceSelection,force); + return force; +} + LLObjectSelection::LLObjectSelection() : std::list(), LLRefCount(), diff --git a/linden/indra/newview/llselectmgr.h b/linden/indra/newview/llselectmgr.h index 7eff94a..fec3a0a 100644 --- a/linden/indra/newview/llselectmgr.h +++ b/linden/indra/newview/llselectmgr.h @@ -239,7 +239,8 @@ public: void updateEffects(); // Update HUD effects void overrideObjectUpdates(); - void setForceSelection(BOOL force) { mForceSelection = force; } + // Returns the previous value of mForceSelection + BOOL setForceSelection(BOOL force); //////////////////////////////////////////////////////////////// // Selection methods @@ -273,7 +274,7 @@ public: //////////////////////////////////////////////////////////////// void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE); - void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE); + void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE, BOOL include_entire_object = FALSE); // Send deselect messages to simulator, then clear the list void deselectAll(); diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 7dbb107..208bb7c 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -85,6 +85,8 @@ #include "lleventnotifier.h" #include "llface.h" #include "llfeaturemanager.h" +#include "llfirstuse.h" +#include "llfloateractivespeakers.h" #include "llfloaterchat.h" #include "llfloatergesture.h" #include "llfloaterland.h" @@ -153,6 +155,7 @@ #include "llfasttimerview.h" #include "llfloatermap.h" #include "llweb.h" +#include "llvoiceclient.h" #if LL_LIBXUL_ENABLED #include "llmozlib.h" @@ -211,6 +214,7 @@ static bool gGotUseCircuitCodeAck = false; LLString gInitialOutfit; LLString gInitialOutfitGender; // "male" or "female" +static bool gUseCircuitCallbackCalled = false; // // local function declaration @@ -783,12 +787,7 @@ BOOL idle_startup() LLFile::mkdir(gDirUtilp->getChatLogsDir().c_str()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir().c_str()); - -#if LL_WINDOWS - if (gSavedSettings.getBOOL("UseDebugLogin") && show_connect_box) -#else if (show_connect_box) -#endif { LLString server_label; S32 domain_name_index; @@ -799,10 +798,16 @@ BOOL idle_startup() { snprintf(gUserServerName, MAX_STRING, "%s", server_label.c_str()); /* Flawfinder: ignore */ } - } - if (show_connect_box) - { + // Dave S temp reversion of SL-49082 fix - this code breaks command line urls. I'll fix this with + // the control isDirty() functionality tomorrow. + + //if ( userPickedServer ) + //{ // User picked a grid from the popup, so clear the stored urls so they will be re-generated from gUserServerChoice + // auth_uris.clear(); + // resetURIs(); + //} + LLString location; LLPanelLogin::getLocation( location ); LLURLSimString::setString( location ); @@ -1159,29 +1164,18 @@ BOOL idle_startup() case LLUserAuth::E_COULDNT_RESOLVE_HOST: case LLUserAuth::E_SSL_PEER_CERTIFICATE: case LLUserAuth::E_UNHANDLED_ERROR: + case LLUserAuth::E_SSL_CACERT: + case LLUserAuth::E_SSL_CONNECT_ERROR: default: - if (auth_uri_num >= (int) auth_uris.size()) + if (auth_uri_num >= (int) auth_uris.size() - 1) { emsg << "Unable to connect to " << gSecondLife << ".\n"; emsg << gUserAuthp->errorMessage(); } else { - std::ostringstream s; - s << "Logging in (attempt " << (auth_uri_num + 1) << "). "; - auth_desc = s.str(); - gStartupState = STATE_LOGIN_AUTHENTICATE; auth_uri_num++; - return do_normal_idle; - } - break; - case LLUserAuth::E_SSL_CACERT: - case LLUserAuth::E_SSL_CONNECT_ERROR: - if (auth_uri_num >= (int) auth_uris.size()) - { - emsg << "Unable to establish a secure connection to the login server.\n"; - emsg << gUserAuthp->errorMessage(); - } else { std::ostringstream s; - s << "Logging in (attempt " << (auth_uri_num + 1) << "). "; + s << "Previous login attempt failed. Logging in, attempt " + << (auth_uri_num + 1) << ". "; auth_desc = s.str(); gStartupState = STATE_LOGIN_AUTHENTICATE; auth_uri_num++; @@ -1431,6 +1425,9 @@ BOOL idle_startup() gAutoLogin = FALSE; show_connect_box = TRUE; } + + // Pass the user information to the voice chat server interface. + gVoiceClient->userAuthorized(firstname, lastname, gAgentID); } else { @@ -1553,12 +1550,21 @@ BOOL idle_startup() { update_texture_fetch(); + if ( gViewerWindow != NULL && gToolMgr != NULL ) + { // This isn't the first logon attempt, so show the UI + gViewerWindow->setNormalControlsVisible( TRUE ); + } + // Initialize UI if (!gNoRender) { // Initialize all our tools. Must be done after saved settings loaded. - gToolMgr = new LLToolMgr(); - gToolMgr->initTools(); + if ( gToolMgr == NULL ) + { + gToolMgr = new LLToolMgr(); + gToolMgr->initTools(); + } + // Quickly get something onscreen to look at. gViewerWindow->initWorldUI(); @@ -1589,14 +1595,20 @@ BOOL idle_startup() gXferManager->registerCallbacks(gMessageSystem); - gCacheName = new LLCacheName(gMessageSystem); - gCacheName->addObserver(callback_cache_name); - - // Load stored cache if possible - load_name_cache(); + if ( gCacheName == NULL ) + { + gCacheName = new LLCacheName(gMessageSystem); + gCacheName->addObserver(callback_cache_name); + + // Load stored cache if possible + load_name_cache(); + } // Data storage for map of world. - gWorldMap = new LLWorldMap(); + if ( gWorldMap == NULL ) + { + gWorldMap = new LLWorldMap(); + } // register null callbacks for audio until the audio system is initialized gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL); @@ -1678,6 +1690,9 @@ BOOL idle_startup() { llwarns << "Attempting to connect to simulator with a zero circuit code!" << llendl; } + + gUseCircuitCallbackCalled = FALSE; + msg->enableCircuit(first_sim, TRUE); // now, use the circuit info to tell simulator about us! llinfos << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << llendl; @@ -1711,14 +1726,7 @@ BOOL idle_startup() { if (gViewerWindow) { - if (gSavedSettings.getBOOL("MuteAudio")) - { - LLMediaEngine::updateClass( 0.0f ); - } - else - { - LLMediaEngine::updateClass( gSavedSettings.getF32( "MediaAudioVolume" ) ); - } + audio_update_volume(true); } #if LL_QUICKTIME_ENABLED // windows only right now but will be ported to mac @@ -2298,6 +2306,9 @@ BOOL idle_startup() // On first start, ask user for gender dialog_choose_gender_first_start(); + // setup voice + LLFirstUse::useVoice(); + // Start automatic replay if the flag is set. if (gSavedSettings.getBOOL("StatsAutoRun")) { @@ -2325,7 +2336,7 @@ BOOL idle_startup() } } } - + // Clean up the userauth stuff. if (gUserAuthp) { @@ -2334,13 +2345,9 @@ BOOL idle_startup() } gStartupState++; - //RN: unmute audio now that we are entering world - //JC: But only if the user wants audio working. - if (gAudiop) - { - BOOL mute = gSavedSettings.getBOOL("MuteAudio"); - gAudiop->setMuted(mute); - } + + // Unmute audio if desired and setup volumes + audio_update_volume(); // reset keyboard focus to sane state of pointing at world gFocusMgr.setKeyboardFocus(NULL, NULL); @@ -2362,9 +2369,15 @@ BOOL idle_startup() void login_show() { llinfos << "Initializing Login Screen" << llendl; - + +#ifdef LL_RELEASE_FOR_DOWNLOAD + BOOL bUseDebugLogin = gSavedSettings.getBOOL("UseDebugLogin"); +#else + BOOL bUseDebugLogin = TRUE; +#endif + LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(), - gSavedSettings.getBOOL("UseDebugLogin"), + bUseDebugLogin, login_callback, NULL ); llinfos << "Decoding Images" << llendl; @@ -2516,7 +2529,10 @@ void save_password_to_disk(const char* hashed_password) LLXORCipher cipher(gMACAddress, 6); cipher.encrypt(buffer, HASHED_LENGTH); - fwrite(buffer, HASHED_LENGTH, 1, fp); + if (fwrite(buffer, HASHED_LENGTH, 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } fclose(fp); } @@ -2810,10 +2826,9 @@ void use_circuit_callback(void**, S32 result) { // bail if we're quitting. if(gQuit) return; - static bool called = false; - if(!called) + if( !gUseCircuitCallbackCalled ) { - called = true; + gUseCircuitCallbackCalled = true; if (result) { // Make sure user knows something bad happened. JC @@ -3731,5 +3746,8 @@ void reset_login() { gStartupState = STATE_LOGIN_SHOW; - // do cleanup here of in-world UI? + if ( gViewerWindow ) + { // Hide menus and normal buttons + gViewerWindow->setNormalControlsVisible( FALSE ); + } } diff --git a/linden/indra/newview/llstatusbar.cpp b/linden/indra/newview/llstatusbar.cpp index f0c6ea5..9d6434f 100644 --- a/linden/indra/newview/llstatusbar.cpp +++ b/linden/indra/newview/llstatusbar.cpp @@ -70,11 +70,14 @@ #include "llviewerparcelmgr.h" #include "llviewerthrottle.h" #include "llvieweruictrlfactory.h" +#include "llvoiceclient.h" // for gVoiceClient #include "lltoolmgr.h" #include "llfocusmgr.h" #include "viewer.h" +//#include "llfirstuse.h" + // // Globals // @@ -96,6 +99,18 @@ const F32 ICON_FLASH_FREQUENCY = 2.f; const S32 GRAPHIC_FUDGE = 4; const S32 TEXT_HEIGHT = 18; +static void onClickParcelInfo(void*); +static void onClickBalance(void*); +static void onClickBuyCurrency(void*); +static void onClickHealth(void*); +static void onClickFly(void*); +static void onClickPush(void*); +static void onClickVoice(void*); +static void onClickBuild(void*); +static void onClickScripts(void*); +static void onClickBuyLand(void*); +static void onClickScriptDebug(void*); + std::vector LLStatusBar::sDays; std::vector LLStatusBar::sMonths; const U32 LLStatusBar::MAX_DATE_STRING_LENGTH = 2000; @@ -126,15 +141,6 @@ LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect) // build date necessary data (must do after panel built) setupDate(); - mBtnScriptOut = LLUICtrlFactory::getButtonByName( this, "scriptout" ); - mBtnHealth = LLUICtrlFactory::getButtonByName( this, "health" ); - mBtnFly = LLUICtrlFactory::getButtonByName( this, "fly" ); - mBtnBuild = LLUICtrlFactory::getButtonByName( this, "build" ); - mBtnScripts = LLUICtrlFactory::getButtonByName( this, "scripts" ); - mBtnPush = LLUICtrlFactory::getButtonByName( this, "restrictpush" ); - mBtnBuyLand = LLUICtrlFactory::getButtonByName( this, "buyland" ); - mBtnBuyCurrency = LLUICtrlFactory::getButtonByName( this, "buycurrency" ); - mTextParcelName = LLUICtrlFactory::getTextBoxByName( this, "ParcelNameText" ); mTextBalance = LLUICtrlFactory::getTextBoxByName( this, "BalanceText" ); @@ -196,6 +202,7 @@ BOOL LLStatusBar::postBuild() childSetAction("build", onClickBuild, this ); childSetAction("scripts", onClickScripts, this ); childSetAction("restrictpush", onClickPush, this ); + childSetAction("status_voice", onClickVoice, this ); childSetActionTextbox("ParcelNameText", onClickParcelInfo ); childSetActionTextbox("BalanceText", onClickBalance ); @@ -305,13 +312,13 @@ void LLStatusBar::refresh() { childGetRect( "scriptout", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnScriptOut->setRect(r); - mBtnScriptOut->setVisible(TRUE); + childSetRect("scriptout",r); + childSetVisible("scriptout", true); x += buttonRect.getWidth(); } else { - mBtnScriptOut->setVisible(FALSE); + childSetVisible("scriptout", false); } if ((region && region->getAllowDamage()) || @@ -320,19 +327,19 @@ void LLStatusBar::refresh() // set visibility based on flashing if( mHealthTimer->hasExpired() ) { - mBtnHealth->setVisible( TRUE ); + childSetVisible("health", true); } else { BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1; - mBtnHealth->setVisible( flash ); + childSetVisible("health", flash); } mTextHealth->setVisible(TRUE); // Health childGetRect( "health", buttonRect ); r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnHealth->setRect(r); + childSetRect("health", r); x += buttonRect.getWidth(); const S32 health_width = S32( LLFontGL::sSansSerifSmall->getWidth("100%") ); @@ -343,7 +350,7 @@ void LLStatusBar::refresh() else { // invisible if region doesn't allow damage - mBtnHealth->setVisible(FALSE); + childSetVisible("health", false); mTextHealth->setVisible(FALSE); } @@ -352,24 +359,24 @@ void LLStatusBar::refresh() { // No Fly Zone childGetRect( "fly", buttonRect ); - mBtnFly->setVisible(TRUE); + childSetVisible( "fly", true ); r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnFly->setRect(r); + childSetRect( "fly", r ); x += buttonRect.getWidth(); } else { - mBtnFly->setVisible(FALSE); + childSetVisible("fly", false); } BOOL no_build = parcel && !parcel->getAllowModify(); - mBtnBuild->setVisible( no_build ); + childSetVisible("build", no_build); if (no_build) { childGetRect( "build", buttonRect ); // No Build Zone r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnBuild->setRect(r); + childSetRect( "build", r ); x += buttonRect.getWidth(); } @@ -381,37 +388,46 @@ void LLStatusBar::refresh() { no_scripts = TRUE; } - mBtnScripts->setVisible( no_scripts ); + childSetVisible("scripts", no_scripts); if (no_scripts) { // No scripts childGetRect( "scripts", buttonRect ); r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnScripts->setRect(r); + childSetRect( "scripts", r ); x += buttonRect.getWidth(); } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); - mBtnPush->setVisible( no_push ); + childSetVisible("restrictpush", no_push); if (no_push) { childGetRect( "restrictpush", buttonRect ); - // No Push Zone r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnPush->setRect(r); + childSetRect( "restrictpush", r ); + x += buttonRect.getWidth(); + } + + BOOL have_voice = gVoiceClient->getAreaVoiceDisabled() ? FALSE : TRUE; + childSetVisible("status_voice", have_voice); + if (have_voice) + { + childGetRect( "status_voice", buttonRect ); + r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); + childSetRect( "status_voice", r ); x += buttonRect.getWidth(); } BOOL canBuyLand = parcel && !parcel->isPublic() && gParcelMgr->canAgentBuyParcel(parcel, false); - mBtnBuyLand->setVisible(canBuyLand); + childSetVisible("buyland", canBuyLand); if (canBuyLand) { childGetRect( "buyland", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); - mBtnBuyLand->setRect(r); + childSetRect( "buyland", r ); x += buttonRect.getWidth(); } @@ -480,7 +496,7 @@ void LLStatusBar::setVisibleForMouselook(bool visible) mTextTime->setVisible(visible); mSGBandwidth->setVisible(visible); mSGPacketLoss->setVisible(visible); - mBtnBuyCurrency->setVisible(visible); + childSetVisible("buycurrency", visible); setBackgroundVisible(visible); } @@ -589,58 +605,55 @@ S32 LLStatusBar::getSquareMetersLeft() const return mSquareMetersCredit - mSquareMetersCommitted; } -// static -void LLStatusBar::onClickParcelInfo(void* data) +static void onClickParcelInfo(void* data) { gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); LLFloaterLand::show(); } -// static -void LLStatusBar::onClickBalance(void* data) +static void onClickBalance(void* data) { LLFloaterBuyCurrency::buyCurrency(); } -// static -void LLStatusBar::onClickBuyCurrency(void* data) +static void onClickBuyCurrency(void* data) { LLFloaterBuyCurrency::buyCurrency(); } -// static -void LLStatusBar::onClickHealth(void* ) +static void onClickHealth(void* ) { LLNotifyBox::showXml("NotSafe"); } -// static -void LLStatusBar::onClickScriptDebug(void*) +static void onClickScriptDebug(void*) { LLFloaterScriptDebug::show(LLUUID::null); } -// static -void LLStatusBar::onClickFly(void* ) +static void onClickFly(void* ) { LLNotifyBox::showXml("NoFly"); } -// static -void LLStatusBar::onClickPush(void* ) +static void onClickPush(void* ) { LLNotifyBox::showXml("PushRestricted"); } -// static -void LLStatusBar::onClickBuild(void*) +static void onClickVoice(void* ) +{ + LLNotifyBox::showXml("VoiceAvailablity"); + //LLFirstUse::useVoice(); +} + +static void onClickBuild(void*) { LLNotifyBox::showXml("NoBuild"); } -// static -void LLStatusBar::onClickScripts(void*) +static void onClickScripts(void*) { LLViewerRegion* region = gAgent.getRegion(); if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) @@ -657,8 +670,7 @@ void LLStatusBar::onClickScripts(void*) } } -// static -void LLStatusBar::onClickBuyLand(void*) +static void onClickBuyLand(void*) { gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); gParcelMgr->startBuyLand(); diff --git a/linden/indra/newview/llstatusbar.h b/linden/indra/newview/llstatusbar.h index e08066b..ff71ee3 100644 --- a/linden/indra/newview/llstatusbar.h +++ b/linden/indra/newview/llstatusbar.h @@ -81,19 +81,7 @@ public: S32 getSquareMetersCommitted() const; S32 getSquareMetersLeft() const; -protected: - static void onClickParcelInfo(void*); - static void onClickBalance(void*); - static void onClickBuyCurrency(void*); - static void onClickRegionInfo(void*); - static void onClickHealth(void*); - static void onClickFly(void*); - static void onClickPush(void*); - static void onClickBuild(void*); - static void onClickScripts(void*); - static void onClickBuyLand(void*); - static void onClickScriptDebug(void*); - +protected: // simple method to setup the part that holds the date void setupDate(); @@ -102,15 +90,6 @@ protected: LLTextBox *mTextHealth; LLTextBox *mTextTime; - LLButton *mBtnScriptOut; - LLButton *mBtnHealth; - LLButton *mBtnFly; - LLButton *mBtnBuild; - LLButton *mBtnScripts; - LLButton *mBtnPush; - LLButton *mBtnBuyLand; - - LLTextBox* mTextParcelName; LLStatGraph *mSGBandwidth; @@ -127,7 +106,7 @@ protected: static std::vector sDays; static std::vector sMonths; - static const U32 LLStatusBar::MAX_DATE_STRING_LENGTH; + static const U32 MAX_DATE_STRING_LENGTH; }; // *HACK: Status bar owns your cached money balance. JC diff --git a/linden/indra/newview/lltoolbar.cpp b/linden/indra/newview/lltoolbar.cpp index 3d065e1..d58cca0 100644 --- a/linden/indra/newview/lltoolbar.cpp +++ b/linden/indra/newview/lltoolbar.cpp @@ -46,6 +46,7 @@ #include "llvoavatar.h" #include "lltooldraganddrop.h" #include "llinventoryview.h" +#include "llfloaterchatterbox.h" #include "llfloaterfriends.h" #include "llfloatersnapshot.h" #include "lltoolmgr.h" @@ -114,15 +115,12 @@ LLToolBar::LLToolBar(const std::string& name, const LLRect& r) BOOL LLToolBar::postBuild() { - childSetAction("im_btn", onClickIM, this); - childSetControlName("im_btn", "ShowIM"); + childSetAction("communicate_btn", onClickCommunicate, this); + childSetControlName("communicate_btn", "ShowCommunicate"); childSetAction("chat_btn", onClickChat, this); childSetControlName("chat_btn", "ChatVisible"); - childSetAction("friends_btn", onClickFriends, this); - childSetControlName("friends_btn", "ShowFriends"); - childSetAction("appearance_btn", onClickAppearance, this); childSetControlName("appearance_btn", ""); @@ -333,24 +331,9 @@ void LLToolBar::refresh() // static -void LLToolBar::onClickIM(void* user_data) +void LLToolBar::onClickCommunicate(void* user_data) { - if(gIMView->getFloaterOpen()) - { - // this is if we want Ctrl-T to be simply a toggle - // gIMView->setFloaterOpen( FALSE ); - // three-state behavior follows - if(gFocusMgr.childHasKeyboardFocus(gIMView->getFloater())) - { - gIMView->setFloaterOpen( FALSE ); - } else { - gIMView->getFloater()->setFocus( TRUE ); - } - } - else - { - gIMView->setFloaterOpen( TRUE ); - } + LLFloaterChatterBox::toggleInstance(LLSD()); } @@ -360,14 +343,6 @@ void LLToolBar::onClickChat(void* user_data) handle_chat(NULL); } - -// static -void LLToolBar::onClickFriends(void*) -{ - LLFloaterFriends::toggle(); -} - - // static void LLToolBar::onClickAppearance(void*) { diff --git a/linden/indra/newview/lltoolbar.h b/linden/indra/newview/lltoolbar.h index 52da849..3e32881 100644 --- a/linden/indra/newview/lltoolbar.h +++ b/linden/indra/newview/lltoolbar.h @@ -67,9 +67,8 @@ public: void refresh(); // callbacks - static void onClickIM(void*); + static void onClickCommunicate(void*); static void onClickChat(void* data); - static void onClickFriends(void* data); static void onClickAppearance(void* data); static void onClickClothing(void* data); static void onClickFly(void*); diff --git a/linden/indra/newview/lltooldraganddrop.cpp b/linden/indra/newview/lltooldraganddrop.cpp index 6196927..655a8dd 100644 --- a/linden/indra/newview/lltooldraganddrop.cpp +++ b/linden/indra/newview/lltooldraganddrop.cpp @@ -1239,7 +1239,6 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, return FALSE; } } -std::cout << "ASSET ID: " << new_item->getAssetUUID() << "\n"; hit_obj->updateInventory(new_item, TASK_INVENTORY_ASSET_KEY, true); } else if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, @@ -1253,7 +1252,6 @@ std::cout << "ASSET ID: " << new_item->getAssetUUID() << "\n"; // *FIX: may want to make sure agent can paint hit_obj. // make sure the object has the texture in it's inventory. -std::cout << "ASSET ID: " << new_item->getAssetUUID() << "\n"; hit_obj->updateInventory(new_item, TASK_INVENTORY_ASSET_KEY, true); } return TRUE; diff --git a/linden/indra/newview/lltoolselect.cpp b/linden/indra/newview/lltoolselect.cpp index 329801f..f400b53 100644 --- a/linden/indra/newview/lltoolselect.cpp +++ b/linden/indra/newview/lltoolselect.cpp @@ -135,7 +135,7 @@ LLHandle LLToolSelect::handleObjectSelection(LLViewerObject * } else { - gSelectMgr->deselectObjectAndFamily(object); + gSelectMgr->deselectObjectAndFamily(object, TRUE, TRUE); } } else diff --git a/linden/indra/newview/lluserauth.cpp b/linden/indra/newview/lluserauth.cpp index 1513175..f790fe7 100644 --- a/linden/indra/newview/lluserauth.cpp +++ b/linden/indra/newview/lluserauth.cpp @@ -57,6 +57,8 @@ static const char* PLATFORM_STRING = "Win"; static const char* PLATFORM_STRING = "Mac"; #elif LL_LINUX static const char* PLATFORM_STRING = "Lnx"; +#elif LL_SOLARIS +static const char* PLATFORM_STRING = "Sol"; #else #error("Unknown platform defined!") #endif diff --git a/linden/indra/newview/llviewercontrol.h b/linden/indra/newview/llviewercontrol.h index 4324c38..46363b1 100644 --- a/linden/indra/newview/llviewercontrol.h +++ b/linden/indra/newview/llviewercontrol.h @@ -54,9 +54,11 @@ protected: LLTextEditor* mComment; }; +// These functions found in llcontroldef.cpp *TODO: clean this up! //setting variables are declared in this function void declare_settings(); void fixup_settings(); +void settings_setup_listeners(); // saved at end of session extern LLControlGroup gSavedSettings; diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h index ee19cfb..9e7689f 100644 --- a/linden/indra/newview/llviewerimage.h +++ b/linden/indra/newview/llviewerimage.h @@ -189,9 +189,27 @@ public: // New methods for determining image quality/priority // texel_area_ratio is ("scaled" texel area)/(original texel area), approximately. + void addTextureStats(F32 pixel_area) const + { + mMaxCosAngle = 1.0f; + if (pixel_area > mMaxVirtualSize) + { + mMaxVirtualSize = pixel_area; + } + } + void addTextureStats(F32 pixel_area, + F32 texel_area_ratio) const + { + mMaxCosAngle = 1.0f; + F32 virtual_size = pixel_area / texel_area_ratio; + if (virtual_size > mMaxVirtualSize) + { + mMaxVirtualSize = virtual_size; + } + } void addTextureStats(F32 pixel_area, - F32 texel_area_ratio = 1.0f, - F32 cos_center_angle = 1.0f) const; + F32 texel_area_ratio, + F32 cos_center_angle) const; void resetTextureStats(BOOL zero = FALSE); // Process image stats to determine priority/quality requirements. diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index 6616bc6..2e3b964 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp @@ -129,6 +129,7 @@ void LLViewerImageList::doPreloadImages() if (!gPreloadImages) return; // Preload some images + preloadImage("active_voice_tab.tga", LLUUID::null, FALSE); preloadImage("button_anim_pause.tga", LLUUID::null, FALSE); preloadImage("button_anim_pause_selected.tga", LLUUID::null, FALSE); preloadImage("button_anim_play.tga", LLUUID::null, FALSE); @@ -205,11 +206,15 @@ void LLViewerImageList::doPreloadImages() preloadImage("map_infohub.tga", LLUUID::null, FALSE); preloadImage("map_telehub.tga", LLUUID::null, FALSE); preloadImage("map_track_16.tga", LLUUID::null, FALSE); + preloadImage("media_icon.tga", LLUUID::null, FALSE); preloadImage("minimize.tga", LLUUID::null, FALSE); preloadImage("minimize_pressed.tga", LLUUID::null, FALSE); + preloadImage("music_icon.tga", LLUUID::null, FALSE); preloadImage("noentrylines.tga", LLUUID::null, TRUE); preloadImage("noentrypasslines.tga", LLUUID::null, TRUE); preloadImage("notify_tip_icon.tga", LLUUID::null, FALSE); + preloadImage("notify_caution_icon.tga", LLUUID::null, FALSE); + preloadImage("notify_box_icon.tga", LLUUID::null, FALSE); preloadImage("object_cone.tga", LLUUID::null, FALSE); preloadImage("object_cone_active.tga", LLUUID::null, FALSE); preloadImage("object_cube.tga", LLUUID::null, FALSE); @@ -283,7 +288,19 @@ void LLViewerImageList::doPreloadImages() preloadImage("tool_dozer_active.tga", LLUUID::null, FALSE); preloadImage("tool_zoom.tga", LLUUID::null, FALSE); preloadImage("tool_zoom_active.tga", LLUUID::null, FALSE); + preloadImage("volume_icon.tga", LLUUID::null, FALSE); preloadImage("white.tga", LLUUID::null, TRUE); + preloadImage("icn_active-speakers-dot-lvl0.tga", LLUUID::null, FALSE); + preloadImage("icn_active-speakers-dot-lvl1.tga", LLUUID::null, FALSE); + preloadImage("icn_active-speakers-dot-lvl2.tga", LLUUID::null, FALSE); + preloadImage("icn_active-speakers-typing1.tga", LLUUID::null, FALSE); + preloadImage("icn_active-speakers-typing2.tga", LLUUID::null, FALSE); + preloadImage("icn_active-speakers-typing3.tga", LLUUID::null, FALSE); + preloadImage("icn_voice_ptt-off.tga", LLUUID::null, FALSE); + preloadImage("icn_voice_ptt-on.tga", LLUUID::null, FALSE); + preloadImage("icn_voice_ptt-on-lvl1.tga", LLUUID::null, FALSE); + preloadImage("icn_voice_ptt-on-lvl2.tga", LLUUID::null, FALSE); + preloadImage("icn_voice_ptt-on-lvl3.tga", LLUUID::null, FALSE); } static std::string get_texture_list_name() diff --git a/linden/indra/newview/llviewerinventory.cpp b/linden/indra/newview/llviewerinventory.cpp index f24b7c7..6372ba8 100644 --- a/linden/indra/newview/llviewerinventory.cpp +++ b/linden/indra/newview/llviewerinventory.cpp @@ -460,7 +460,11 @@ bool LLViewerInventoryCategory::importFileLocal(FILE* fp) valuestr[0] = '\0'; while(!feof(fp)) { - fgets(buffer, MAX_STRING, fp); + if (fgets(buffer, MAX_STRING, fp) == NULL) + { + buffer[0] = '\0'; + } + sscanf( /* Flawfinder: ignore */ buffer, " %254s %254s", keyword, valuestr); if(0 == strcmp("{",keyword)) diff --git a/linden/indra/newview/llviewerjointattachment.cpp b/linden/indra/newview/llviewerjointattachment.cpp index cec2ae3..f75ac48 100644 --- a/linden/indra/newview/llviewerjointattachment.cpp +++ b/linden/indra/newview/llviewerjointattachment.cpp @@ -50,16 +50,17 @@ extern LLPipeline gPipeline; //----------------------------------------------------------------------------- // LLViewerJointAttachment() //----------------------------------------------------------------------------- -LLViewerJointAttachment::LLViewerJointAttachment() +LLViewerJointAttachment::LLViewerJointAttachment() : +mJoint(NULL), +mAttachedObject(NULL), +mAttachmentDirty(FALSE), +mVisibleInFirst(FALSE), +mGroup(0), +mIsHUDAttachment(FALSE), +mPieSlice(-1) { - mJoint = NULL; - mAttachedObject = NULL; - mAttachmentDirty = FALSE; - mGroup = 0; - mUpdateXform = FALSE; - mIsHUDAttachment = FALSE; mValid = FALSE; - mPieSlice = -1; + mUpdateXform = FALSE; } //----------------------------------------------------------------------------- diff --git a/linden/indra/newview/llviewerjointmesh.cpp b/linden/indra/newview/llviewerjointmesh.cpp index c76990c..09fd015 100644 --- a/linden/indra/newview/llviewerjointmesh.cpp +++ b/linden/indra/newview/llviewerjointmesh.cpp @@ -31,14 +31,11 @@ //----------------------------------------------------------------------------- #include "llviewerprecompiledheaders.h" -#if LL_WINDOWS // For Intel vector classes - #include "fvec.h" -#endif - #include "imageids.h" #include "llfasttimer.h" #include "llagent.h" +#include "llapr.h" #include "llbox.h" #include "lldrawable.h" #include "lldrawpoolavatar.h" @@ -49,14 +46,19 @@ #include "llglheaders.h" #include "lltexlayer.h" #include "llviewercamera.h" +#include "llviewercontrol.h" #include "llviewerimagelist.h" #include "llviewerjointmesh.h" #include "llvoavatar.h" #include "llsky.h" #include "pipeline.h" #include "llglslshader.h" +#include "llmath.h" +#include "v4math.h" +#include "m3math.h" +#include "m4math.h" -#if !LL_DARWIN && !LL_LINUX +#if !LL_DARWIN && !LL_LINUX && !LL_SOLARIS extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB; extern PFNGLWEIGHTFVARBPROC glWeightfvARB; extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB; @@ -68,6 +70,7 @@ static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD; + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // LLViewerJointMesh::LLSkinJoint @@ -120,6 +123,7 @@ BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint) return TRUE; } + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // LLViewerJointMesh @@ -414,9 +418,9 @@ const S32 NUM_AXES = 3; // rotation Z 0-n // pivot parent 0-n -- child = n+1 -static LLMatrix4 gJointMat[32]; -static LLMatrix3 gJointRot[32]; -static LLVector4 gJointPivot[32]; +static LLMatrix4 gJointMatUnaligned[32]; +static LLMatrix3 gJointRotUnaligned[32]; +static LLVector4 gJointPivot[32]; //----------------------------------------------------------------------------- // uploadJointMatrices() @@ -437,8 +441,8 @@ void LLViewerJointMesh::uploadJointMatrices() { joint_mat *= LLDrawPoolAvatar::getModelView(); } - gJointMat[joint_num] = joint_mat; - gJointRot[joint_num] = joint_mat.getMat3(); + gJointMatUnaligned[joint_num] = joint_mat; + gJointRotUnaligned[joint_num] = joint_mat.getMat3(); } BOOL last_pivot_uploaded = FALSE; @@ -475,8 +479,8 @@ void LLViewerJointMesh::uploadJointMatrices() { LLVector3 pivot; pivot = LLVector3(gJointPivot[i]); - pivot = pivot * gJointRot[i]; - gJointMat[i].translate(pivot); + pivot = pivot * gJointRotUnaligned[i]; + gJointMatUnaligned[i].translate(pivot); } // upload matrices @@ -487,11 +491,11 @@ void LLViewerJointMesh::uploadJointMatrices() for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++) { - gJointMat[joint_num].transpose(); + gJointMatUnaligned[joint_num].transpose(); for (S32 axis = 0; axis < NUM_AXES; axis++) { - F32* vector = gJointMat[joint_num].mMatrix[axis]; + F32* vector = gJointMatUnaligned[joint_num].mMatrix[axis]; //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+5, (GLfloat*)vector); U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num; memcpy(mat+offset*4, vector, sizeof(GLfloat)*4); @@ -903,21 +907,9 @@ BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate) return (valid != activate); } - -void LLViewerJointMesh::updateGeometry() +// static +void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh) { - if (!(mValid - && mMesh - && mFace - && mMesh->hasWeights() - && mFace->mVertexBuffer.notNull() - && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) == 0)) - { - return; - } - - uploadJointMatrices(); - LLStrider o_vertices; LLStrider o_normals; @@ -958,9 +950,9 @@ void LLViewerJointMesh::updateGeometry() // No lerp required in this case. if (w == 1.0f) { - gBlendMat = gJointMat[joint+1]; + gBlendMat = gJointMatUnaligned[joint+1]; o_vertices[bidx] = coords[index] * gBlendMat; - gBlendRotMat = gJointRot[joint+1]; + gBlendRotMat = gJointRotUnaligned[joint+1]; o_normals[bidx] = normals[index] * gBlendRotMat; continue; } @@ -968,8 +960,8 @@ void LLViewerJointMesh::updateGeometry() // Try to keep all the accesses to the matrix data as close // together as possible. This function is a hot spot on the // Mac. JC - LLMatrix4 &m0 = gJointMat[joint+1]; - LLMatrix4 &m1 = gJointMat[joint+0]; + LLMatrix4 &m0 = gJointMatUnaligned[joint+1]; + LLMatrix4 &m1 = gJointMatUnaligned[joint+0]; gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w); gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w); @@ -989,8 +981,8 @@ void LLViewerJointMesh::updateGeometry() o_vertices[bidx] = coords[index] * gBlendMat; - LLMatrix3 &n0 = gJointRot[joint+1]; - LLMatrix3 &n1 = gJointRot[joint+0]; + LLMatrix3 &n0 = gJointRotUnaligned[joint+1]; + LLMatrix3 &n1 = gJointRotUnaligned[joint+0]; gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w); gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w); @@ -1008,6 +1000,161 @@ void LLViewerJointMesh::updateGeometry() } } +const U32 UPDATE_GEOMETRY_CALL_MASK = 0x1FFF; // 8K samples before overflow +const U32 UPDATE_GEOMETRY_CALL_OVERFLOW = ~UPDATE_GEOMETRY_CALL_MASK; +static bool sUpdateGeometryCallPointer = false; +static F64 sUpdateGeometryGlobalTime = 0.0 ; +static F64 sUpdateGeometryElapsedTime = 0.0 ; +static F64 sUpdateGeometryElapsedTimeOff = 0.0 ; +static F64 sUpdateGeometryElapsedTimeOn = 0.0 ; +static F64 sUpdateGeometryRunAvgOff[10]; +static F64 sUpdateGeometryRunAvgOn[10]; +static U32 sUpdateGeometryRunCount = 0 ; +static U32 sUpdateGeometryCalls = 0 ; +static U32 sUpdateGeometryLastProcessor = 0 ; +void (*LLViewerJointMesh::sUpdateGeometryFunc)(LLFace* face, LLPolyMesh* mesh); + +void LLViewerJointMesh::updateGeometry() +{ + extern BOOL gVectorizePerfTest; + extern U32 gVectorizeProcessor; + + if (!(mValid + && mMesh + && mFace + && mMesh->hasWeights() + && mFace->mVertexBuffer.notNull() + && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) == 0)) + { + return; + } + + if (!gVectorizePerfTest) + { + // Once we've measured performance, just run the specified + // code version. + if(sUpdateGeometryFunc == updateGeometryOriginal) + uploadJointMatrices(); + sUpdateGeometryFunc(mFace, mMesh); + } + else + { + // At startup, measure the amount of time in skinning and choose + // the fastest one. + LLTimer ug_timer ; + + if (sUpdateGeometryCallPointer) + { + if(sUpdateGeometryFunc == updateGeometryOriginal) + uploadJointMatrices(); + // call accelerated version for this processor + sUpdateGeometryFunc(mFace, mMesh); + } + else + { + uploadJointMatrices(); + updateGeometryOriginal(mFace, mMesh); + } + + sUpdateGeometryElapsedTime += ug_timer.getElapsedTimeF64(); + ++sUpdateGeometryCalls; + if(0 != (sUpdateGeometryCalls & UPDATE_GEOMETRY_CALL_OVERFLOW)) + { + F64 time_since_app_start = ug_timer.getElapsedSeconds(); + if(sUpdateGeometryGlobalTime == 0.0 + || sUpdateGeometryLastProcessor != gVectorizeProcessor) + { + sUpdateGeometryGlobalTime = time_since_app_start; + sUpdateGeometryElapsedTime = 0; + sUpdateGeometryCalls = 0; + sUpdateGeometryRunCount = 0; + sUpdateGeometryLastProcessor = gVectorizeProcessor; + sUpdateGeometryCallPointer = false; + return; + } + F64 percent_time_in_function = + ( sUpdateGeometryElapsedTime * 100.0 ) / ( time_since_app_start - sUpdateGeometryGlobalTime ) ; + sUpdateGeometryGlobalTime = time_since_app_start; + if (!sUpdateGeometryCallPointer) + { + // First set of run data is with vectorization off. + sUpdateGeometryCallPointer = true; + llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = " + << "vectorize off " << percent_time_in_function + << "% of time with " + << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls) + << " seconds per call " + << llendl; + sUpdateGeometryRunAvgOff[sUpdateGeometryRunCount] = percent_time_in_function; + sUpdateGeometryElapsedTimeOff += sUpdateGeometryElapsedTime; + sUpdateGeometryCalls = 0; + } + else + { + // Second set of run data is with vectorization on. + sUpdateGeometryCallPointer = false; + llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = " + << "VEC on " << percent_time_in_function + << "% of time with " + << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls) + << " seconds per call " + << llendl; + sUpdateGeometryRunAvgOn[sUpdateGeometryRunCount] = percent_time_in_function ; + sUpdateGeometryElapsedTimeOn += sUpdateGeometryElapsedTime; + + sUpdateGeometryCalls = 0; + sUpdateGeometryRunCount++; + F64 a = 0.0, b = 0.0; + for(U32 i = 0; i 0.0) + { + llinfos << "Vectorization improves avatar skinning performance, " + << "keeping on for future runs." + << llendl; + gSavedSettings.setBOOL("VectorizeSkin", TRUE); + } + else + { + // SIMD decreases performance, fall back to original code + llinfos << "Vectorization decreases avatar skinning performance, " + << "switching back to original code." + << llendl; + + gSavedSettings.setBOOL("VectorizeSkin", FALSE); + } + } + } + sUpdateGeometryElapsedTime = 0.0f; + } + } +} + void LLViewerJointMesh::dump() { if (mValid) diff --git a/linden/indra/newview/llviewerjointmesh.h b/linden/indra/newview/llviewerjointmesh.h index f016da6..b40daed 100644 --- a/linden/indra/newview/llviewerjointmesh.h +++ b/linden/indra/newview/llviewerjointmesh.h @@ -146,6 +146,22 @@ public: /*virtual*/ BOOL isAnimatable() { return FALSE; } void writeCAL3D(apr_file_t* fp, S32 material_num, LLCharacter* characterp); + + // Avatar vertex skinning is a significant performance issue on computers + // with avatar vertex programs turned off (for example, most Macs). We + // therefore have custom versions that use SIMD instructions. + // + // These functions require compiler options for SSE2, SSE, or neither, and + // hence are contained in separate individual .cpp files. JC + static void updateGeometryOriginal(LLFace* face, LLPolyMesh* mesh); + // generic vector code, used for Altivec + static void updateGeometryVectorized(LLFace* face, LLPolyMesh* mesh); + static void updateGeometrySSE(LLFace* face, LLPolyMesh* mesh); + static void updateGeometrySSE2(LLFace* face, LLPolyMesh* mesh); + + // Use a fuction pointer to indicate which version we are running. + static void (*sUpdateGeometryFunc)(LLFace* face, LLPolyMesh* mesh); + private: // Allocate skin data BOOL allocateSkinData( U32 numSkinJoints ); diff --git a/linden/indra/newview/llviewerjointmesh_sse.cpp b/linden/indra/newview/llviewerjointmesh_sse.cpp new file mode 100644 index 0000000..95d621a --- /dev/null +++ b/linden/indra/newview/llviewerjointmesh_sse.cpp @@ -0,0 +1,114 @@ +/** + * @file llviewerjointmesh_sse.cpp + * @brief SSE vectorized joint skinning code, only used when video card does + * not support avatar vertex programs. + * + * *NOTE: Disabled on Windows builds. See llv4math.h for details. + * + * Copyright (c) 2007-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- + +#include "llviewerprecompiledheaders.h" + +#include "llviewerjointmesh.h" + +// project includes +#include "llface.h" +#include "llpolymesh.h" + +// library includes +#include "lldarray.h" +#include "llv4math.h" // for LL_VECTORIZE +#include "llv4matrix3.h" +#include "llv4matrix4.h" +#include "v3math.h" + + +#if LL_VECTORIZE + +inline void matrix_translate(LLV4Matrix4& m, const LLMatrix4* w, const LLVector3& j) +{ + m.mV[VX] = _mm_loadu_ps(w->mMatrix[VX]); + m.mV[VY] = _mm_loadu_ps(w->mMatrix[VY]); + m.mV[VZ] = _mm_loadu_ps(w->mMatrix[VZ]); + m.mV[VW] = _mm_loadu_ps(w->mMatrix[VW]); + m.mV[VW] = _mm_add_ps(m.mV[VW], _mm_mul_ps(_mm_set1_ps(j.mV[VX]), m.mV[VX])); // ( ax * vx ) + vw + m.mV[VW] = _mm_add_ps(m.mV[VW], _mm_mul_ps(_mm_set1_ps(j.mV[VY]), m.mV[VY])); + m.mV[VW] = _mm_add_ps(m.mV[VW], _mm_mul_ps(_mm_set1_ps(j.mV[VZ]), m.mV[VZ])); +} + +// static +void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh) +{ + // This cannot be a file-level static because it will be initialized + // before main() using SSE code, which will crash on non-SSE processors. + static LLV4Matrix4 sJointMat[32]; + LLDynamicArray& joint_data = mesh->getReferenceMesh()->mJointRenderData; + + //upload joint pivots/matrices + for(S32 j = 0, jend = joint_data.count(); j < jend ; ++j ) + { + matrix_translate(sJointMat[j], joint_data[j]->mWorldMatrix, + joint_data[j]->mSkinJoint ? + joint_data[j]->mSkinJoint->mRootToJointSkinOffset + : joint_data[j+1]->mSkinJoint->mRootToParentJointSkinOffset); + } + + F32 weight = F32_MAX; + LLV4Matrix4 blend_mat; + + LLStrider o_vertices; + LLStrider o_normals; + + LLVertexBuffer *buffer = face->mVertexBuffer; + buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); + buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); + + const F32* weights = mesh->getWeights(); + const LLVector3* coords = mesh->getCoords(); + const LLVector3* normals = mesh->getNormals(); + for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) + { + if( weight != weights[index]) + { + S32 joint = llfloor(weight = weights[index]); + blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); + } + blend_mat.multiply(coords[index], o_vertices[index]); + ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); + } +} + +#else + +void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh) +{ + LLViewerJointMesh::updateGeometryVectorized(face, mesh); +} + +#endif diff --git a/linden/indra/newview/llviewerjointmesh_sse2.cpp b/linden/indra/newview/llviewerjointmesh_sse2.cpp new file mode 100644 index 0000000..27aab80 --- /dev/null +++ b/linden/indra/newview/llviewerjointmesh_sse2.cpp @@ -0,0 +1,121 @@ +/** + * @file llviewerjointmesh_sse2.cpp + * @brief SSE vectorized joint skinning code, only used when video card does + * not support avatar vertex programs. + * + * *NOTE: Disabled on Windows builds. See llv4math.h for details. + * + * Copyright (c) 2007-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +// Visual Studio required settings for this file: +// Precompiled Headers OFF +// Code Generation: SSE2 + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- + +#include "llviewerprecompiledheaders.h" + +#include "llviewerjointmesh.h" + +// project includes +#include "llface.h" +#include "llpolymesh.h" + +// library includes +#include "lldarray.h" +#include "llstrider.h" +#include "llv4math.h" // for LL_VECTORIZE +#include "llv4matrix3.h" +#include "llv4matrix4.h" +#include "m4math.h" +#include "v3math.h" + + +#if LL_VECTORIZE + + +inline void matrix_translate(LLV4Matrix4& m, const LLMatrix4* w, const LLVector3& j) +{ + m.mV[VX] = _mm_loadu_ps(w->mMatrix[VX]); + m.mV[VY] = _mm_loadu_ps(w->mMatrix[VY]); + m.mV[VZ] = _mm_loadu_ps(w->mMatrix[VZ]); + m.mV[VW] = _mm_loadu_ps(w->mMatrix[VW]); + m.mV[VW] = _mm_add_ps(m.mV[VW], _mm_mul_ps(_mm_set1_ps(j.mV[VX]), m.mV[VX])); // ( ax * vx ) + vw + m.mV[VW] = _mm_add_ps(m.mV[VW], _mm_mul_ps(_mm_set1_ps(j.mV[VY]), m.mV[VY])); + m.mV[VW] = _mm_add_ps(m.mV[VW], _mm_mul_ps(_mm_set1_ps(j.mV[VZ]), m.mV[VZ])); +} + +// static +void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh) +{ + // This cannot be a file-level static because it will be initialized + // before main() using SSE code, which will crash on non-SSE processors. + static LLV4Matrix4 sJointMat[32]; + LLDynamicArray& joint_data = mesh->getReferenceMesh()->mJointRenderData; + + //upload joint pivots/matrices + for(S32 j = 0, jend = joint_data.count(); j < jend ; ++j ) + { + matrix_translate(sJointMat[j], joint_data[j]->mWorldMatrix, + joint_data[j]->mSkinJoint ? + joint_data[j]->mSkinJoint->mRootToJointSkinOffset + : joint_data[j+1]->mSkinJoint->mRootToParentJointSkinOffset); + } + + F32 weight = F32_MAX; + LLV4Matrix4 blend_mat; + + LLStrider o_vertices; + LLStrider o_normals; + + LLVertexBuffer *buffer = face->mVertexBuffer; + buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); + buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); + + const F32* weights = mesh->getWeights(); + const LLVector3* coords = mesh->getCoords(); + const LLVector3* normals = mesh->getNormals(); + for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) + { + if( weight != weights[index]) + { + S32 joint = llfloor(weight = weights[index]); + blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); + } + blend_mat.multiply(coords[index], o_vertices[index]); + ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); + } +} + +#else + +void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh) +{ + LLViewerJointMesh::updateGeometryVectorized(face, mesh); +} + +#endif diff --git a/linden/indra/newview/llviewerjointmesh_vec.cpp b/linden/indra/newview/llviewerjointmesh_vec.cpp new file mode 100644 index 0000000..39c50de --- /dev/null +++ b/linden/indra/newview/llviewerjointmesh_vec.cpp @@ -0,0 +1,95 @@ +/** + * @file llviewerjointmesh_vec.cpp + * @brief Compiler-generated vectorized joint skinning code, works well on + * Altivec processors (PowerPC Mac) + * + * *NOTE: See llv4math.h for notes on SSE/Altivec vector code. + * + * Copyright (c) 2007-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llviewerprecompiledheaders.h" + +#include "llviewerjointmesh.h" + +#include "llface.h" +#include "llpolymesh.h" +#include "llv4math.h" +#include "llv4matrix3.h" +#include "llv4matrix4.h" + +// Generic vectorized code, uses compiler defaults, works well for Altivec +// on PowerPC. + +// static +void LLViewerJointMesh::updateGeometryVectorized(LLFace *face, LLPolyMesh *mesh) +{ + static LLV4Matrix4 sJointMat[32]; + LLDynamicArray& joint_data = mesh->getReferenceMesh()->mJointRenderData; + S32 j, joint_num, joint_end = joint_data.count(); + LLV4Vector3 pivot; + + //upload joint pivots/matrices + for(j = joint_num = 0; joint_num < joint_end ; ++joint_num ) + { + LLSkinJoint *sj; + const LLMatrix4 * wm = joint_data[joint_num]->mWorldMatrix; + if (NULL == (sj = joint_data[joint_num]->mSkinJoint)) + { + sj = joint_data[++joint_num]->mSkinJoint; + ((LLV4Matrix3)(sJointMat[j] = *wm)).multiply(sj->mRootToParentJointSkinOffset, pivot); + sJointMat[j++].translate(pivot); + wm = joint_data[joint_num]->mWorldMatrix; + } + ((LLV4Matrix3)(sJointMat[j] = *wm)).multiply(sj->mRootToJointSkinOffset, pivot); + sJointMat[j++].translate(pivot); + } + + F32 weight = F32_MAX; + LLV4Matrix4 blend_mat; + + LLStrider o_vertices; + LLStrider o_normals; + + LLVertexBuffer *buffer = face->mVertexBuffer; + buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); + buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); + + const F32* weights = mesh->getWeights(); + const LLVector3* coords = mesh->getCoords(); + const LLVector3* normals = mesh->getNormals(); + for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) + { + if( weight != weights[index]) + { + S32 joint = llfloor(weight = weights[index]); + blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); + } + blend_mat.multiply(coords[index], o_vertices[index]); + ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); + } +} diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index 31d10df..4ac1da4 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp @@ -79,6 +79,8 @@ #include "llfloater.h" #include "llfloaterabout.h" #include "llfloaterbuycurrency.h" +#include "llfloateractivespeakers.h" +#include "llfloateranimpreview.h" #include "llfloateravatarinfo.h" #include "llfloateravatartextures.h" #include "llfloaterbuildoptions.h" @@ -91,6 +93,7 @@ #include "llfloatercustomize.h" #include "llfloaterdirectory.h" #include "llfloatereditui.h" +#include "llfloaterchatterbox.h" #include "llfloaterfriends.h" #include "llfloatergesture.h" #include "llfloatergodtools.h" @@ -735,7 +738,7 @@ void init_client_menu(LLMenuGL* menu) // neither of these works particularly well at the moment /*menu->append(new LLMenuItemCallGL( "Reload UI XML", &reload_ui, - NULL, NULL, 'R', MASK_ALT | MASK_CONTROL ) );*/ + NULL, NULL) );*/ /*menu->append(new LLMenuItemCallGL("Reload settings/colors", &handle_reload_settings, NULL, NULL));*/ menu->append(new LLMenuItemCallGL("Reload personal setting overrides", @@ -893,7 +896,7 @@ void init_client_menu(LLMenuGL* menu) (void*)"LimitSelectDistance")); menu->append(new LLMenuItemToggleGL("Disable Camera Constraints", - &LLViewerCamera::sDisableCameraConstraints)); + &LLViewerCamera::sDisableCameraConstraints, 'C', MASK_ALT | MASK_CONTROL )); menu->append(new LLMenuItemCheckGL("Joystick Flycam", &handle_toggle_flycam,NULL,&check_flycam,NULL)); @@ -980,6 +983,7 @@ extern BOOL gDebugClicks; extern BOOL gDebugWindowProc; extern BOOL gDebugTextEditorTips; extern BOOL gDebugSelectMgr; +extern BOOL gVectorizePerfTest; void init_debug_ui_menu(LLMenuGL* menu) { @@ -1094,39 +1098,39 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("UI", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_UI, '1', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_UI, KEY_F1, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Selected", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_SELECTED, '2', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_SELECTED, KEY_F2, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Highlighted", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED, '3', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED, KEY_F3, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Dynamic Textures", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES, '4', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES, KEY_F4, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL( "Foot Shadows", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS, '5', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS, KEY_F5, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Fog", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOG, '6', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOG, KEY_F6, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Palletized Textures", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_PALETTE, '7', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_PALETTE, KEY_F7, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Test FRInfo", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO, '8', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO, KEY_F8, MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL( "Flexible Objects", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE, '9', MASK_ALT|MASK_CONTROL)); + (void*)LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE, KEY_F9, MASK_ALT|MASK_CONTROL)); sub_menu->createJumpKeys(); ///////////////////////////// @@ -1189,6 +1193,8 @@ void init_debug_rendering_menu(LLMenuGL* menu) (void*)"ShowDepthBuffer")); sub_menu->append(new LLMenuItemToggleGL("Show Select Buffer", &gDebugSelect)); + sub_menu->append(new LLMenuItemToggleGL("Vectorize Perf Test", &gVectorizePerfTest)); + sub_menu = new LLMenuGL("Render Tests"); sub_menu->append(new LLMenuItemCheckGL("Camera Offset", @@ -1296,7 +1302,7 @@ void init_debug_avatar_menu(LLMenuGL* menu) menu->append(new LLMenuItemToggleGL( "Display Agent Target", &LLAgent::sDebugDisplayTarget)); menu->append(new LLMenuItemToggleGL( "Debug Rotation", &gDebugAvatarRotation)); menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); - menu->append(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures)); + menu->append(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL )); #ifndef LL_RELEASE_FOR_DOWNLOAD menu->append(new LLMenuItemCallGL("Debug Avatar Textures", handle_debug_avatar_textures, NULL, NULL, 'A', MASK_SHIFT|MASK_CONTROL|MASK_ALT)); menu->append(new LLMenuItemCallGL("Dump Local Textures", handle_dump_avatar_local_textures, NULL, NULL, 'M', MASK_SHIFT|MASK_ALT )); @@ -2339,10 +2345,11 @@ void handle_buy_object(LLSaleInfo sale_info) return; } - if(sale_info.getSalePrice() > gStatusBar->getBalance()) + S32 price = sale_info.getSalePrice(); + + if (price > 0 && price > gStatusBar->getBalance()) { - LLFloaterBuyCurrency::buyCurrency( - "This object costs", sale_info.getSalePrice()); + LLFloaterBuyCurrency::buyCurrency("This object costs", price); return; } @@ -2470,7 +2477,7 @@ void set_god_level(U8 god_level) U8 old_god_level = gAgent.getGodLevel(); gAgent.setGodLevel( god_level ); show_debug_menus(); - gIMView->refresh(); + gIMMgr->refresh(); gParcelMgr->notifyObservers(); // Some classifieds change visibility on god mode @@ -2554,7 +2561,7 @@ void load_url_local_file(const char* file_name) gAgent.changeCameraToDefault(); } -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || LL_SOLARIS // MBW -- If the Mac client is in fullscreen mode, it needs to go windowed so the browser will be visible. if(gViewerWindow->mWindow->getFullscreen()) { @@ -2673,7 +2680,7 @@ void request_friendship(const LLUUID& dest_id) } if (!fullname.empty()) { - LLFloaterFriends::requestFriendship(dest_id, fullname); + LLPanelFriends::requestFriendship(dest_id, fullname); LLNotifyBox::showXml("OfferedFriendship", args); } else @@ -5371,7 +5378,7 @@ class LLShowFloater : public view_listener_t } else if (floater_name == "friends") { - LLFloaterFriends::toggle(NULL); + LLFloaterMyFriends::toggleInstance(0); } else if (floater_name == "preferences") { @@ -5383,11 +5390,11 @@ class LLShowFloater : public view_listener_t } else if (floater_name == "chat history") { - LLFloaterChat::toggle(NULL); + LLFloaterChat::toggleInstance(LLSD()); } else if (floater_name == "im") { - LLToolBar::onClickIM(NULL); + LLFloaterChatterBox::toggleInstance(LLSD()); } else if (floater_name == "inventory") { @@ -5496,6 +5503,10 @@ class LLShowFloater : public view_listener_t { LLFloaterAbout::show(NULL); } + else if (floater_name == "active speakers") + { + LLFloaterActiveSpeakers::toggleInstance(LLSD()); + } return true; } }; @@ -5509,7 +5520,7 @@ class LLFloaterVisible : public view_listener_t bool new_value = false; if (floater_name == "friends") { - new_value = LLFloaterFriends::visible(NULL); + new_value = LLFloaterMyFriends::instanceVisible(0); } else if (floater_name == "toolbar") { @@ -5521,7 +5532,7 @@ class LLFloaterVisible : public view_listener_t } else if (floater_name == "im") { - new_value = gIMView && gIMView->mTalkFloater && gIMView->mTalkFloater->getVisible(); + new_value = LLFloaterMyFriends::instanceVisible(0); } else if (floater_name == "mute list") { @@ -5539,6 +5550,10 @@ class LLFloaterVisible : public view_listener_t { new_value = gDebugView->mStatViewp->getVisible(); } + else if (floater_name == "active speakers") + { + new_value = LLFloaterActiveSpeakers::instanceVisible(LLSD()); + } gMenuHolder->findControl(control_name)->setValue(new_value); return true; } @@ -5655,19 +5670,7 @@ class LLShowAgentGroups : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLUUID agent_id; - if (userdata.asString() == "agent") - { - agent_id = gAgent.getID(); - } - else - { - agent_id = userdata.asUUID(); - } - if(agent_id.notNull()) - { - LLFloaterGroups::show(agent_id, LLFloaterGroups::AGENT_GROUPS); - } + LLFloaterMyFriends::toggleInstance(1); return true; } }; @@ -6167,10 +6170,10 @@ class LLAvatarSendIM : public view_listener_t name.append( last->getString() ); } - gIMView->setFloaterOpen(TRUE); + gIMMgr->setFloaterOpen(TRUE); //EInstantMessage type = have_agent_callingcard(gLastHitObjectID) // ? IM_SESSION_ADD : IM_SESSION_CARDLESS_START; - gIMView->addSession(name, + gIMMgr->addSession(name, IM_NOTHING_SPECIAL, avatar->getID()); } @@ -7316,22 +7319,66 @@ class LLViewToggleBeacon : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { LLString beacon = userdata.asString(); - if (beacon == "scripts") + if (beacon == "scriptsbeacon") { LLPipeline::toggleRenderScriptedBeacons(NULL); + gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); + // toggle the other one off if it's on + if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) + { + LLPipeline::toggleRenderScriptedTouchBeacons(NULL); + gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); + } } - else if (beacon == "physical") + else if (beacon == "physicalbeacon") { LLPipeline::toggleRenderPhysicalBeacons(NULL); + gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) ); } - else if (beacon == "sounds") + else if (beacon == "soundsbeacon") { LLPipeline::toggleRenderSoundBeacons(NULL); + gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) ); } - else if (beacon == "particles") + else if (beacon == "particlesbeacon") { LLPipeline::toggleRenderParticleBeacons(NULL); + gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) ); } + else if (beacon == "scripttouchbeacon") + { + LLPipeline::toggleRenderScriptedTouchBeacons(NULL); + gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); + // toggle the other one off if it's on + if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) + { + LLPipeline::toggleRenderScriptedBeacons(NULL); + gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); + } + } + else if (beacon == "renderbeacons") + { + LLPipeline::toggleRenderBeacons(NULL); + gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); + // toggle the other one on if it's not + if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) + { + LLPipeline::toggleRenderHighlights(NULL); + gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); + } + } + else if (beacon == "renderhighlights") + { + LLPipeline::toggleRenderHighlights(NULL); + gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); + // toggle the other one on if it's not + if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) + { + LLPipeline::toggleRenderBeacons(NULL); + gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); + } + } + return true; } }; @@ -7342,21 +7389,40 @@ class LLViewCheckBeaconEnabled : public view_listener_t { LLString beacon = userdata["data"].asString(); bool new_value = false; - if (beacon == "scripts") + if (beacon == "scriptsbeacon") + { + new_value = gSavedSettings.getBOOL( "scriptsbeacon"); + LLPipeline::setRenderScriptedBeacons(new_value); + } + else if (beacon == "physicalbeacon") + { + new_value = gSavedSettings.getBOOL( "physicalbeacon"); + LLPipeline::setRenderPhysicalBeacons(new_value); + } + else if (beacon == "soundsbeacon") + { + new_value = gSavedSettings.getBOOL( "soundsbeacon"); + LLPipeline::setRenderSoundBeacons(new_value); + } + else if (beacon == "particlesbeacon") { - new_value = LLPipeline::getRenderScriptedBeacons(NULL); + new_value = gSavedSettings.getBOOL( "particlesbeacon"); + LLPipeline::setRenderParticleBeacons(new_value); } - else if (beacon == "physical") + else if (beacon == "scripttouchbeacon") { - new_value = LLPipeline::getRenderPhysicalBeacons(NULL); + new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); + LLPipeline::setRenderScriptedTouchBeacons(new_value); } - else if (beacon == "sounds") + else if (beacon == "renderbeacons") { - new_value = LLPipeline::getRenderSoundBeacons(NULL); + new_value = gSavedSettings.getBOOL( "renderbeacons"); + LLPipeline::setRenderBeacons(new_value); } - else if (beacon == "particles") + else if (beacon == "renderhighlights") { - new_value = LLPipeline::getRenderParticleBeacons(NULL); + new_value = gSavedSettings.getBOOL( "renderhighlights"); + LLPipeline::setRenderHighlights(new_value); } gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; @@ -7384,7 +7450,7 @@ class LLViewCheckRenderType : public view_listener_t bool new_value = false; if (type == "particles") { - new_value = LLPipeline::toggleRenderTypeControlNegated((void *)(S32)LLPipeline::RENDER_TYPE_PARTICLES); + new_value = LLPipeline::toggleRenderTypeControlNegated((void *)LLPipeline::RENDER_TYPE_PARTICLES); } gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; diff --git a/linden/indra/newview/llviewermenufile.cpp b/linden/indra/newview/llviewermenufile.cpp index d0b8c73..4d46a8f 100644 --- a/linden/indra/newview/llviewermenufile.cpp +++ b/linden/indra/newview/llviewermenufile.cpp @@ -222,7 +222,7 @@ class LLFileUploadImage : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - const char* filename = upload_pick((void *)(S32)LLFilePicker::FFLOAD_IMAGE); + const char* filename = upload_pick((void *)LLFilePicker::FFLOAD_IMAGE); if (filename) { LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); @@ -236,7 +236,7 @@ class LLFileUploadSound : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_WAV)); + const char* filename = upload_pick((void*)LLFilePicker::FFLOAD_WAV); if (filename) { LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); @@ -250,7 +250,7 @@ class LLFileUploadAnim : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_ANIM)); + const char* filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM); if (filename) { LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); @@ -691,7 +691,10 @@ void upload_new_resource(const LLString& src_filename, std::string name, S16 type_num; // read in and throw out most of the header except for the type - fread(buf, header_size, 1, in); + if (fread(buf, header_size, 1, in) != 1) + { + llwarns << "Short read" << llendl; + } memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */ asset_type = (LLAssetType::EType)type_num; } @@ -702,7 +705,10 @@ void upload_new_resource(const LLString& src_filename, std::string name, { while((read = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ { - fwrite(buf, 1, read, out); /* Flawfinder: ignore */ + if (fwrite(buf, 1, read, out) != read) + { + llwarns << "Short write" << llendl; + } } fclose(out); } diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index d45cf34..6bca17e 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -63,6 +63,7 @@ #include "message.h" #include "sound_ids.h" #include "lltimer.h" +#include "llmd5.h" #include "llagent.h" #include "llcallingcard.h" @@ -70,6 +71,7 @@ #include "llviewercontrol.h" #include "lldrawpool.h" #include "llfirstuse.h" +#include "llfloateractivespeakers.h" #include "llfloaterbuycurrency.h" #include "llfloaterbuyland.h" #include "llfloaterchat.h" @@ -341,10 +343,15 @@ void export_complete() FILE* fXML = LLFile::fopen(gExportedFile.c_str(), "rb"); /* Flawfinder: ignore */ fseek(fXML, 0, SEEK_END); - U32 length = ftell(fXML); + long length = ftell(fXML); fseek(fXML, 0, SEEK_SET); - U8 *buffer = new U8[length]; - fread(buffer, 1, length, fXML); + U8 *buffer = new U8[length + 1]; + size_t nread = fread(buffer, 1, length, fXML); + if (nread < (size_t) length) + { + llwarns << "Short read" << llendl; + } + buffer[nread] = '\0'; fclose(fXML); char *pos = (char *)buffer; @@ -380,7 +387,10 @@ void export_complete() } FILE* fXMLOut = LLFile::fopen(gExportedFile.c_str(), "wb"); /* Flawfinder: ignore */ - fwrite(buffer, 1, length, fXMLOut); + if (fwrite(buffer, 1, length, fXMLOut) != length) + { + llwarns << "Short write" << llendl; + } fclose(fXMLOut); delete [] buffer; @@ -442,7 +452,10 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) S32 length = ftell(fIn); fseek(fIn, 0, SEEK_SET); U8 *buffer = ImageUtility->allocateData(length); - fread(buffer, 1, length, fIn); + if (fread(buffer, 1, length, fIn) != length) + { + llwarns << "Short read" << llendl; + } fclose(fIn); LLFile::remove(filename.c_str()); @@ -469,7 +482,10 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) strcpy(md5_hash_string, "00000000000000000000000000000000"); /* Flawfinder: ignore */ if (fOut) { - fwrite(data, 1, data_size, fOut); + if (fwrite(data, 1, data_size, fOut) != data_size) + { + llwarns << "Short write" << llendl; + } fseek(fOut, 0, SEEK_SET); fclose(fOut); fOut = LLFile::fopen(output_file.c_str(), "rb"); /* Flawfinder: ignore */ @@ -1322,7 +1338,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) time_t timestamp = (time_t)t; BOOL is_busy = gAgent.getBusy(); - BOOL is_muted = gMuteListp->isMuted(from_id, name); + BOOL is_muted = gMuteListp->isMuted(from_id, name, LLMute::flagTextChat); BOOL is_linden = gMuteListp->isLinden(name); BOOL is_owned_by_me = FALSE; @@ -1373,7 +1389,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { // return a standard "busy" message, but only do it to online IM // (i.e. not other auto responses and not store-and-forward IM) - if (!gIMView->hasSession(session_id)) + if (!gIMMgr->hasSession(session_id)) { // if there is not a panel for this conversation (i.e. it is a new IM conversation // initiated by the other party) then... @@ -1398,14 +1414,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) snprintf(buffer, sizeof(buffer), "%s%s%s", name, separator_string, (message+message_offset)); /* Flawfinder: ignore */ - if(from_id == gAgentID) - { - from_id = LLUUID::null; - } llinfos << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << llendl; // add to IM panel, but do not bother the user - gIMView->addMessage( + gIMMgr->addMessage( session_id, from_id, name, @@ -1455,15 +1467,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) formatted_time(timestamp, time_buf)); } snprintf(buffer, sizeof(buffer), "%s%s%s%s", name, separator_string, saved,(message+message_offset)); /* Flawfinder: ignore */ - if(from_id == gAgentID) - { - from_id = LLUUID::null; - } + llinfos << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << llendl; if (!is_muted || is_linden) { - gIMView->addMessage( + gIMMgr->addMessage( session_id, from_id, name, @@ -1494,14 +1503,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_TYPING_START: { LLPointer im_info = new LLIMInfo(gMessageSystem); - gIMView->processIMTypingStart(im_info); + gIMMgr->processIMTypingStart(im_info); } break; case IM_TYPING_STOP: { LLPointer im_info = new LLIMInfo(gMessageSystem); - gIMView->processIMTypingStop(im_info); + gIMMgr->processIMTypingStop(im_info); } break; @@ -1734,12 +1743,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) return; } - // System messages, specifically "Foo Bar has left this session" - // are not shown unless you actually have that session open. - // Band-aid. JC - if (offline == IM_ONLINE - && chat.mFromName == SYSTEM_FROM - && !gIMView->hasSession(session_id)) + // Only show messages if we have a session open (which + // should happen after you get an "invitation" + if ( !gIMMgr->hasSession(session_id) ) { return; } @@ -1759,10 +1765,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) BOOL is_this_agent = FALSE; if(from_id == gAgentID) { - from_id = LLUUID::null; is_this_agent = TRUE; } - gIMView->addMessage( + gIMMgr->addMessage( session_id, from_id, name, @@ -1813,7 +1818,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) else { // original code resumes - gIMView->addMessage(session_id, from_id, name, message); + gIMMgr->addMessage(session_id, from_id, name, message); } break; @@ -2079,7 +2084,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) if(!source_name.empty()) { if (gAgent.getBusy() - || gMuteListp->isMuted(source_id, source_name)) + || gMuteListp->isMuted(source_id, source_name, LLMute::flagTextChat)) { // automatically decline offer callingcard_offer_callback(1, (void*)offerdata); @@ -2155,7 +2160,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) BOOL is_linden = FALSE; if (gMuteListp) { - is_muted = gMuteListp->isMuted(from_id, from_name) + is_muted = gMuteListp->isMuted(from_id, from_name, LLMute::flagTextChat) || gMuteListp->isMuted(owner_id); is_linden = gMuteListp->isLinden(from_name); } @@ -2179,16 +2184,15 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) gWorldPointer->mPartSim.addPartSource(psc); } - // only pay attention to other people chatting + // record last audible utterance if (is_audible - && (is_linden || (!is_muted && !is_busy)) - && chatter != gAgent.getAvatarObject()) + && (is_linden || (!is_muted && !is_busy))) { - gAgent.heardChat(chat); - if (ll_rand(2) == 0) + if (chat.mChatType != CHAT_TYPE_START + && chat.mChatType != CHAT_TYPE_STOP) { - gAgent.setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero); - } + gAgent.heardChat(chat.mFromID); + } } is_owned_by_me = chatter->permYouOwner(); @@ -2219,6 +2223,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // Look for the start of typing so we can put "..." in the bubbles. if (CHAT_TYPE_START == chat.mChatType) { + gLocalSpeakerMgr->setSpeakerTyping(from_id, TRUE); + // Might not have the avatar constructed yet, eg on login. if (chatter && chatter->isAvatar()) { @@ -2228,6 +2234,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } else if (CHAT_TYPE_STOP == chat.mChatType) { + gLocalSpeakerMgr->setSpeakerTyping(from_id, FALSE); + // Might not have the avatar constructed yet, eg on login. if (chatter && chatter->isAvatar()) { @@ -2239,6 +2247,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // We have a real utterance now, so can stop showing "..." and proceed. if (chatter && chatter->isAvatar()) { + gLocalSpeakerMgr->setSpeakerTyping(from_id, FALSE); ((LLVOAvatar*)chatter)->stopTyping(); if (!is_muted && !is_busy) @@ -2367,7 +2376,7 @@ void process_teleport_start(LLMessageSystem *msg, void**) gTeleportDisplay = TRUE; gAgent.setTeleportState( LLAgent::TELEPORT_START ); make_ui_sound("UISndTeleportOut"); - + // Don't call LLFirstUse::useTeleport here because this could be // due to being killed, which would send you home, not to a Telehub } @@ -2748,7 +2757,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) { avatarp->mFootPlane.clearVec(); } - + // reset always run status msg->newMessageFast(_PREHASH_SetAlwaysRun); msg->nextBlockFast(_PREHASH_AgentData); @@ -3212,7 +3221,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **) if (!gParcelMgr->canHearSound(pos_global)) return; // Don't play sounds triggered by someone you muted. - if (gMuteListp->isMuted(owner_id)) return; + if (gMuteListp->isMuted(owner_id, LLMute::flagObjectSounds)) return; // Don't play sounds from an object you muted if (gMuteListp->isMuted(object_id)) return; @@ -3224,7 +3233,8 @@ void process_sound_trigger(LLMessageSystem *msg, void **) return; } - gAudiop->triggerSound(sound_id, owner_id, gain, pos_global); + F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX"); + gAudiop->triggerSound(sound_id, owner_id, volume, pos_global); } void process_preload_sound(LLMessageSystem *msg, void **user_data) @@ -3246,7 +3256,7 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) if (!objectp) return; if (gMuteListp->isMuted(object_id)) return; - if (gMuteListp->isMuted(owner_id)) return; + if (gMuteListp->isMuted(owner_id, LLMute::flagObjectSounds)) return; LLAudioSource *sourcep = objectp->getAudioSource(owner_id); if (!sourcep) return; @@ -3284,7 +3294,7 @@ void process_attached_sound(LLMessageSystem *msg, void **user_data) if (gMuteListp->isMuted(object_id)) return; - if (gMuteListp->isMuted(owner_id)) return; + if (gMuteListp->isMuted(owner_id, LLMute::flagObjectSounds)) return; objectp->setAttachedSound(sound_id, owner_id, gain, flags); } diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index d237614..f8095b8 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp @@ -176,6 +176,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mLatestRecvPacketID(0), mData(NULL), mAudioSourcep(NULL), + mAudioGain(1.f), mAppAngle(0.f), mPixelArea(1024.f), mInventory(NULL), @@ -2717,6 +2718,12 @@ void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) BOOL LLViewerObject::updateLOD() { + // Update volume of looping sounds + if (mAudioSourcep && mAudioSourcep->isLoop()) + { + F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX"); + mAudioSourcep->setGain(volume); + } return FALSE; } @@ -4057,7 +4064,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own { LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, block_num); //If the owner is muted, don't create the system - if(gMuteListp->isMuted(owner_id)) return; + if(gMuteListp->isMuted(owner_id, LLMute::flagParticles)) return; // We need to be able to deal with a particle source that hasn't changed, but still got an update! if (pss) @@ -4106,7 +4113,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_ { LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); //If the owner is muted, don't create the system - if(gMuteListp->isMuted(owner_id)) return; + if(gMuteListp->isMuted(owner_id, LLMute::flagParticles)) return; // We need to be able to deal with a particle source that hasn't changed, but still got an update! if (pss) { @@ -4224,7 +4231,9 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow if (mAudioSourcep) { BOOL queue = flags & LL_SOUND_FLAG_QUEUE; - mAudioSourcep->setGain(gain); + mAudioGain = gain; + F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX"); + mAudioSourcep->setGain(volume); mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP); mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER); mAudioSourcep->setSyncSlave(flags & LL_SOUND_FLAG_SYNC_SLAVE); @@ -4259,12 +4268,12 @@ void LLViewerObject::adjustAudioGain(const F32 gain) { return; } - - if (!mAudioSourcep) + if (mAudioSourcep) { - return; + mAudioGain = gain; + F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX"); + mAudioSourcep->setGain(volume); } - mAudioSourcep->setGain(gain); } //---------------------------------------------------------------------------- diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h index 2e92672..fcb246c 100644 --- a/linden/indra/newview/llviewerobject.h +++ b/linden/indra/newview/llviewerobject.h @@ -564,8 +564,9 @@ protected: U8* mData; LLPointer mPartSourcep; // Particle source associated with this object. - LLAudioSourceVO *mAudioSourcep; - + LLAudioSourceVO* mAudioSourcep; + F32 mAudioGain; + F32 mAppAngle; // Apparent visual arc in degrees F32 mPixelArea; // Apparent area in pixels diff --git a/linden/indra/newview/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp index 44aa5c7..9f008a4 100644 --- a/linden/indra/newview/llviewerobjectlist.cpp +++ b/linden/indra/newview/llviewerobjectlist.cpp @@ -61,7 +61,11 @@ #include "u64.h" #include "llviewerimagelist.h" #include "lldatapacker.h" -#include +#ifdef LL_STANDALONE +#include +#else +#include "zlib/zlib.h" +#endif #include "object_flags.h" extern BOOL gVelocityInterpolate; diff --git a/linden/indra/newview/llviewerparcelmgr.cpp b/linden/indra/newview/llviewerparcelmgr.cpp index ac56681..31c7d97 100644 --- a/linden/indra/newview/llviewerparcelmgr.cpp +++ b/linden/indra/newview/llviewerparcelmgr.cpp @@ -180,8 +180,7 @@ LLViewerParcelMgr::~LLViewerParcelMgr() delete[] mCollisionSegments; mCollisionSegments = NULL; - // weird, this crashes if I use an array delete on it! - delete sPackedOverlay; + delete[] sPackedOverlay; sPackedOverlay = NULL; delete[] mAgentParcelOverlay; @@ -1793,13 +1792,10 @@ void optionally_start_music(const LLString& music_url) // now only play music when you enter a new parcel if the control is in PLAY state // changed as part of SL-4878 - if ( gOverlayBar->getMusicRemoteControl ()->getTransportState () == LLMediaRemoteCtrl::Play ) + if ( gOverlayBar && gOverlayBar->musicPlaying() ) { - if (gAudiop) - { - gAudiop->startInternetStream(music_url.c_str()); - } - }; + LLOverlayBar::musicPlay(NULL); + } } } @@ -1812,12 +1808,7 @@ void callback_start_music(S32 option, void* data) { gSavedSettings.setBOOL("AudioStreamingMusic", TRUE); llinfos << "Starting first parcel music " << music_url << llendl; - if (gAudiop) - { - gAudiop->startInternetStream(music_url->c_str()); - LLMediaRemoteCtrl* ctrl = gOverlayBar->getMusicRemoteControl(); - ctrl->setTransportState( LLMediaRemoteCtrl::Play, FALSE ); - } + LLOverlayBar::musicPlay(NULL); } else { diff --git a/linden/indra/newview/llviewerpartsim.cpp b/linden/indra/newview/llviewerpartsim.cpp index 914eb2d..bc15317 100644 --- a/linden/indra/newview/llviewerpartsim.cpp +++ b/linden/indra/newview/llviewerpartsim.cpp @@ -41,7 +41,7 @@ #include "llworld.h" #include "pipeline.h" -const S32 MAX_PART_COUNT = 4096; +const S32 MAX_PART_COUNT = 8192; // VWR-1105 const F32 PART_SIM_BOX_SIDE = 16.f; const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE; diff --git a/linden/indra/newview/llviewerpartsource.cpp b/linden/indra/newview/llviewerpartsource.cpp index c0de13a..836748a 100644 --- a/linden/indra/newview/llviewerpartsource.cpp +++ b/linden/indra/newview/llviewerpartsource.cpp @@ -305,6 +305,12 @@ void LLViewerPartSourceScript::update(const F32 dt) //llwarns << "Unknown source pattern " << (S32)mPartSysData.mPattern << llendl; } + if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK || // SVC-193, VWR-717 + part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK) + { + mPartSysData.mBurstRadius = 0; + } + gWorldPointer->mPartSim.addPart(part); } diff --git a/linden/indra/newview/llviewerprecompiledheaders.h b/linden/indra/newview/llviewerprecompiledheaders.h index cc2af01..632fa22 100644 --- a/linden/indra/newview/llviewerprecompiledheaders.h +++ b/linden/indra/newview/llviewerprecompiledheaders.h @@ -92,7 +92,6 @@ #include "llmap.h" #include "llmemory.h" #include "llnametable.h" -#include "llpagemem.h" #include "llpriqueuemap.h" #include "llprocessor.h" #include "llptrskiplist.h" @@ -138,7 +137,6 @@ #include "llcoordframe.h" #include "llcrc.h" #include "llinterp.h" -#include "llmd5.h" #include "llperlin.h" #include "llplane.h" #include "llquantize.h" diff --git a/linden/indra/newview/llviewerregion.cpp b/linden/indra/newview/llviewerregion.cpp index 0f20fd8..0a21e45 100644 --- a/linden/indra/newview/llviewerregion.cpp +++ b/linden/indra/newview/llviewerregion.cpp @@ -202,8 +202,9 @@ void LLViewerRegion::loadCache() } U32 zero; - fread(&zero, 1, sizeof(U32), fp); - if (zero) + size_t nread; + nread = fread(&zero, sizeof(U32), 1, fp); + if (nread != 1 || zero) { // a non-zero value here means bad things! // skip reading the cached values @@ -213,8 +214,8 @@ void LLViewerRegion::loadCache() } U32 version; - fread(&version, 1, sizeof(U32), fp); - if (version != INDRA_OBJECT_CACHE_VERSION) + nread = fread(&version, sizeof(U32), 1, fp); + if (nread != 1 || version != INDRA_OBJECT_CACHE_VERSION) { // a version mismatch here means we've changed the binary format! // skip reading the cached values @@ -224,8 +225,8 @@ void LLViewerRegion::loadCache() } LLUUID cache_id; - fread(&cache_id.mData, UUID_BYTES, sizeof(U8), fp); - if (mCacheID != cache_id) + nread = fread(&cache_id.mData, 1, UUID_BYTES, fp); + if (nread != UUID_BYTES || mCacheID != cache_id) { llinfos << "Cache ID doesn't match for this region, discarding" << llendl; @@ -234,7 +235,14 @@ void LLViewerRegion::loadCache() } S32 num_entries; - fread(&num_entries, 1, sizeof(S32), fp); + nread = fread(&num_entries, sizeof(S32), 1, fp); + if (nread != 1) + { + llinfos << "Short read, discarding" << llendl; + fclose(fp); + return; + } + S32 i; for (i = 0; i < num_entries; i++) { @@ -284,16 +292,28 @@ void LLViewerRegion::saveCache() // write out zero to indicate a version cache file U32 zero = 0; - fwrite(&zero, 1, sizeof(U32), fp); + if (fwrite(&zero, sizeof(U32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } // write out version number U32 version = INDRA_OBJECT_CACHE_VERSION; - fwrite(&version, 1, sizeof(U32), fp); + if (fwrite(&version, sizeof(U32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } // write the cache id for this sim - fwrite(&mCacheID.mData, UUID_BYTES, sizeof(U8), fp); + if (fwrite(&mCacheID.mData, 1, UUID_BYTES, fp) != UUID_BYTES) + { + llwarns << "Short write" << llendl; + } - fwrite(&num_entries, 1, sizeof(S32), fp); + if (fwrite(&num_entries, sizeof(S32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } LLVOCacheEntry *entry; @@ -321,89 +341,15 @@ void LLViewerRegion::sendReliableMessage() gMessageSystem->sendReliable(mHost); } - -void LLViewerRegion::setAllowDamage(BOOL b) -{ - if (b) - { - mRegionFlags |= REGION_FLAGS_ALLOW_DAMAGE; - } - else - { - mRegionFlags &= ~REGION_FLAGS_ALLOW_DAMAGE; - } -} - - -void LLViewerRegion::setAllowLandmark(BOOL b) -{ - if (b) - { - mRegionFlags |= REGION_FLAGS_ALLOW_LANDMARK; - } - else - { - mRegionFlags &= ~REGION_FLAGS_ALLOW_LANDMARK; - } -} - -void LLViewerRegion::setAllowSetHome(BOOL b) -{ - if (b) - { - mRegionFlags |= REGION_FLAGS_ALLOW_SET_HOME; - } - else - { - mRegionFlags &= ~REGION_FLAGS_ALLOW_SET_HOME; - } -} - -void LLViewerRegion::setResetHomeOnTeleport(BOOL b) +void LLViewerRegion::setFlags(BOOL b, U32 flags) { if (b) { - mRegionFlags |= REGION_FLAGS_RESET_HOME_ON_TELEPORT; + mRegionFlags |= flags; } else { - mRegionFlags &= ~REGION_FLAGS_RESET_HOME_ON_TELEPORT; - } -} - -void LLViewerRegion::setSunFixed(BOOL b) -{ - if (b) - { - mRegionFlags |= REGION_FLAGS_SUN_FIXED; - } - else - { - mRegionFlags &= ~REGION_FLAGS_SUN_FIXED; - } -} - -void LLViewerRegion::setBlockFly(BOOL b) -{ - if (b) - { - mRegionFlags |= REGION_FLAGS_BLOCK_FLY; - } - else - { - mRegionFlags &= ~REGION_FLAGS_BLOCK_FLY; - } -} - -void LLViewerRegion::setAllowDirectTeleport(BOOL b) -{ - if (b) - { - mRegionFlags |= REGION_FLAGS_ALLOW_DIRECT_TELEPORT; - } - else - { - mRegionFlags &= ~REGION_FLAGS_ALLOW_DIRECT_TELEPORT; + mRegionFlags &= ~flags; } } @@ -737,14 +683,7 @@ void LLViewerRegion::calculateCenterGlobal() mCenterGlobal = mOriginGlobal; mCenterGlobal.mdV[VX] += 0.5 * mWidth; mCenterGlobal.mdV[VY] += 0.5 * mWidth; - if (mLandp) - { - mCenterGlobal.mdV[VZ] = 0.5*mLandp->getMinZ() + mLandp->getMaxZ(); - } - else - { - mCenterGlobal.mdV[VZ] = F64( getWaterHeight() ); - } + mCenterGlobal.mdV[VZ] = 0.5*mLandp->getMinZ() + mLandp->getMaxZ(); } void LLViewerRegion::calculateCameraDistance() @@ -867,13 +806,23 @@ F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos) { - return mParcelOverlay->isOwnedSelf(pos); + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedSelf(pos); + } else { + return FALSE; + } } // Owned by a group you belong to? (officer or member) BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos) { - return mParcelOverlay->isOwnedGroup(pos); + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedGroup(pos); + } else { + return FALSE; + } } void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) @@ -1325,9 +1274,10 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ChatSessionRequest"); + capabilityNames.append("ProvisionVoiceAccountRequest"); llinfos << "posting to seed " << url << llendl; - + LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this)); } diff --git a/linden/indra/newview/llviewerregion.h b/linden/indra/newview/llviewerregion.h index 8ac5de2..6407f0c 100644 --- a/linden/indra/newview/llviewerregion.h +++ b/linden/indra/newview/llviewerregion.h @@ -83,13 +83,14 @@ public: void setOriginGlobal(const LLVector3d &origin); void setAgentOffset(const LLVector3d &offset); - void setAllowDamage(BOOL b); - void setAllowLandmark(BOOL b); - void setAllowSetHome(BOOL b); - void setResetHomeOnTeleport(BOOL b); - void setSunFixed(BOOL b); - void setBlockFly(BOOL b); - void setAllowDirectTeleport(BOOL b); + void setAllowDamage(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_DAMAGE); } + void setAllowLandmark(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_LANDMARK); } + void setAllowSetHome(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_SET_HOME); } + void setResetHomeOnTeleport(BOOL b) { setFlags(b, REGION_FLAGS_RESET_HOME_ON_TELEPORT); } + void setSunFixed(BOOL b) { setFlags(b, REGION_FLAGS_SUN_FIXED); } + void setBlockFly(BOOL b) { setFlags(b, REGION_FLAGS_BLOCK_FLY); } + void setAllowDirectTeleport(BOOL b) { setFlags(b, REGION_FLAGS_ALLOW_DIRECT_TELEPORT); } + inline BOOL getAllowDamage() const; inline BOOL getAllowLandmark() const; @@ -248,6 +249,7 @@ public: protected: void disconnectAllNeighbors(); void initStats(); + void setFlags(BOOL b, U32 flags); public: LLWind mWind; diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp index f6829d4..3369125 100644 --- a/linden/indra/newview/llviewertexteditor.cpp +++ b/linden/indra/newview/llviewertexteditor.cpp @@ -1267,8 +1267,8 @@ void LLViewerTextEditor::openEmbeddedSound( LLInventoryItem* item ) const F32 SOUND_GAIN = 1.0f; if(gAudiop) { - gAudiop->triggerSound( - item->getAssetUUID(), gAgentID, SOUND_GAIN, lpos_global); + F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); + gAudiop->triggerSound(item->getAssetUUID(), gAgentID, volume, lpos_global); } showCopyToInvDialog( item ); } @@ -1437,7 +1437,7 @@ LLView* LLViewerTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlF LLViewerTextEditor* text_editor = new LLViewerTextEditor(name, rect, max_text_length, - text, + "", font, allow_embedded_items); @@ -1453,7 +1453,18 @@ LLView* LLViewerTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlF node->getAttributeBOOL("hide_scrollbar",hide_scrollbar); text_editor->setHideScrollbarForShortDocs(hide_scrollbar); + BOOL hide_border = !text_editor->mBorder->getVisible(); + node->getAttributeBOOL("hide_border", hide_border); + text_editor->setBorderVisible(!hide_border); + + BOOL parse_html = text_editor->mParseHTML; + node->getAttributeBOOL("allow_html", parse_html); + text_editor->setParseHTML(parse_html); + text_editor->initFromXML(node, parent); + // add text after all parameters have been set + text_editor->appendStyledText(text, FALSE, FALSE, NULL); + return text_editor; } diff --git a/linden/indra/newview/llvieweruictrlfactory.cpp b/linden/indra/newview/llvieweruictrlfactory.cpp index efab1cc..188c905 100644 --- a/linden/indra/newview/llvieweruictrlfactory.cpp +++ b/linden/indra/newview/llvieweruictrlfactory.cpp @@ -41,7 +41,6 @@ #include "llnameeditor.h" #include "llnamelistctrl.h" #include "llwebbrowserctrl.h" -#include "llvolumesliderctrl.h" #include "lljoystickbutton.h" #include "llmediaremotectrl.h" #include "v4color.h" @@ -66,7 +65,6 @@ LLViewerUICtrlFactory::LLViewerUICtrlFactory() #if LL_LIBXUL_ENABLED LLUICtrlCreator::registerCreator(LL_WEB_BROWSER_CTRL_TAG, this); #endif - LLUICtrlCreator::registerCreator(LL_VOLUME_SLIDER_CTRL_TAG, this); LLUICtrlCreator::registerCreator(LL_JOYSTICK_SLIDE, this); LLUICtrlCreator::registerCreator(LL_JOYSTICK_TURN, this); LLUICtrlCreator::registerCreator(LL_MEDIA_REMOTE_CTRL_TAG, this); @@ -103,11 +101,6 @@ LLWebBrowserCtrl* LLViewerUICtrlFactory::getWebBrowserByName(LLPanel* panelp, co return (LLWebBrowserCtrl*)panelp->getCtrlByNameAndType(name, WIDGET_TYPE_WEBBROWSER); } -LLVolumeSliderCtrl* LLViewerUICtrlFactory::getVolumeSliderByName(LLPanel* panelp, const LLString& name) -{ - return (LLVolumeSliderCtrl*)panelp->getCtrlByNameAndType(name, WIDGET_TYPE_VOLUME_SLIDER); -} - LLViewerTextEditor* LLViewerUICtrlFactory::getViewerTextEditorByName(LLPanel* panelp, const LLString& name) { return (LLViewerTextEditor*)panelp->getCtrlByNameAndType(name, WIDGET_TYPE_TEXT_EDITOR); diff --git a/linden/indra/newview/llvieweruictrlfactory.h b/linden/indra/newview/llvieweruictrlfactory.h index de9964e..9664732 100644 --- a/linden/indra/newview/llvieweruictrlfactory.h +++ b/linden/indra/newview/llvieweruictrlfactory.h @@ -38,7 +38,6 @@ class LLNameListCtrl; class LLNameEditor; class LLTextureCtrl; class LLWebBrowserCtrl; -class LLVolumeSliderCtrl; class LLViewerTextEditor; class LLMediaRemoteCtrl; class LLJoystickAgentTurn; @@ -56,7 +55,6 @@ public: static LLNameListCtrl* getNameListByName(LLPanel* panelp, const LLString& name); static LLTextureCtrl* getTexturePickerByName(LLPanel* panelp, const LLString& name); static LLWebBrowserCtrl* getWebBrowserByName(LLPanel* panelp, const LLString& name); - static LLVolumeSliderCtrl* getVolumeSliderByName( LLPanel* panelp, const LLString& name); static LLViewerTextEditor* getViewerTextEditorByName( LLPanel* panelp, const LLString& name); static LLNameEditor* getNameEditorByName(LLPanel* panelp, const LLString& name); static LLMediaRemoteCtrl* getMediaRemoteByName(LLPanel* panelp, const LLString& name); diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index d2190cc..13a4c41 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -39,6 +39,8 @@ #include "llviewercamera.h" //#include "imdebug.h" +#include "llvoiceclient.h" // for push-to-talk button handling + #ifdef SABINRIG #include "cbw.h" #endif //SABINRIG @@ -87,9 +89,11 @@ #include "llfeaturemanager.h" #include "llfilepicker.h" #include "llfloater.h" +#include "llfloateractivespeakers.h" #include "llfloaterbuildoptions.h" #include "llfloaterbuyland.h" #include "llfloaterchat.h" +#include "llfloaterchatterbox.h" #include "llfloatercustomize.h" #include "llfloatereditui.h" // HACK JAMESDEBUG for ui editor #include "llfloaterland.h" @@ -227,7 +231,9 @@ BOOL gPickTransparent = TRUE; BOOL gDebugFastUIRender = FALSE; BOOL gbCapturing = FALSE; +#if !LL_SOLARIS MovieMaker gMovieMaker; +#endif S32 CHAT_BAR_HEIGHT = 28; S32 OVERLAY_BAR_HEIGHT = 20; @@ -515,30 +521,40 @@ public: ypos += y_inc; } - if (LLPipeline::getRenderParticleBeacons(NULL)) - { - addText(xpos, ypos, "Viewing particle beacons (blue)"); - ypos += y_inc; - } - if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES)) - { - addText(xpos, ypos, "Hiding particles"); - ypos += y_inc; - } - if (LLPipeline::getRenderPhysicalBeacons(NULL)) - { - addText(xpos, ypos, "Viewing physical object beacons (green)"); - ypos += y_inc; - } - if (LLPipeline::getRenderScriptedBeacons(NULL)) - { - addText(xpos, ypos, "Viewing scripted object beacons (red)"); - ypos += y_inc; - } - if (LLPipeline::getRenderSoundBeacons(NULL)) + // only display these messages if we are actually rendering beacons at this moment + if (LLPipeline::getRenderBeacons(NULL) && LLPipeline::getProcessBeacons(NULL)) { - addText(xpos, ypos, "Viewing sound beacons (yellow)"); - ypos += y_inc; + if (LLPipeline::getRenderParticleBeacons(NULL)) + { + addText(xpos, ypos, "Viewing particle beacons (blue)"); + ypos += y_inc; + } + if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES)) + { + addText(xpos, ypos, "Hiding particles"); + ypos += y_inc; + } + if (LLPipeline::getRenderPhysicalBeacons(NULL)) + { + addText(xpos, ypos, "Viewing physical object beacons (green)"); + ypos += y_inc; + } + if (LLPipeline::getRenderScriptedBeacons(NULL)) + { + addText(xpos, ypos, "Viewing scripted object beacons (red)"); + ypos += y_inc; + } + else + if (LLPipeline::getRenderScriptedTouchBeacons(NULL)) + { + addText(xpos, ypos, "Viewing scripted object with touch function beacons (red)"); + ypos += y_inc; + } + if (LLPipeline::getRenderSoundBeacons(NULL)) + { + addText(xpos, ypos, "Viewing sound beacons (yellow)"); + ypos += y_inc; + } } } @@ -596,6 +612,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask // Hide tooltips on mousedown if( mToolTip ) { + mToolTipBlocked = TRUE; mToolTip->setVisible( FALSE ); } @@ -1096,6 +1113,21 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK m return TRUE; } +BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) +{ + gVoiceClient->middleMouseState(true); + + // Always handled as far as the OS is concerned. + return TRUE; +} + +BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) +{ + gVoiceClient->middleMouseState(false); + + // Always handled as far as the OS is concerned. + return TRUE; +} void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask) { @@ -1112,7 +1144,8 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask LLCoordGL prev_saved_mouse_point = mCurrentMousePoint; LLCoordGL mouse_point(x, y); saveLastMouse(mouse_point); - BOOL mouse_actually_moved = (prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY); + BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() && // mouse is not currenty captured + ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position gMouseIdleTimer.reset(); @@ -1224,6 +1257,9 @@ void LLViewerWindow::handleFocusLost(LLWindow *window) BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated) { + // Let the voice chat code check for its PTT key. Note that this never affects event processing. + gVoiceClient->keyDown(key, mask); + if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME) { gAgent.clearAFK(); @@ -1243,6 +1279,9 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated) BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask) { + // Let the voice chat code check for its PTT key. Note that this never affects event processing. + gVoiceClient->keyUp(key, mask); + return FALSE; } @@ -1285,21 +1324,14 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) } // Unmute audio - if (!gSavedSettings.getBOOL("MuteAudio")) - { - if (gAudiop) gAudiop->setMuted(FALSE); - F32 volume = gSavedSettings.getF32("MediaAudioVolume"); - if(LLMediaEngine::getInstance()) - { - LLMediaEngine::getInstance()->setVolume(volume); - LLMediaEngine::updateClass(volume); - } - } + audio_update_volume(); } else { mActive = FALSE; - gAgent.setAFK(); + if (gAllowIdleAFK) { + gAgent.setAFK(); + } send_agent_pause(); if (mWindow->getFullscreen() && !mIgnoreActivate) { @@ -1307,14 +1339,7 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) stopGL(); } // Mute audio - if (gSavedSettings.getBOOL("MuteWhenMinimized")) - { - llinfos << "Muting audio on minimize" << llendl; - if (gAudiop) gAudiop->setMuted(TRUE); - F32 volume = 0.f; - LLMediaEngine::getInstance()->setVolume(volume); - LLMediaEngine::updateClass(volume); - } + audio_update_volume(); } return TRUE; } @@ -1463,8 +1488,8 @@ LLViewerWindow::LLViewerWindow( if (NULL == mWindow) { LLSplashScreen::update("Shutting down..."); -#if LL_LINUX - llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt for further information." +#if LL_LINUX || LL_SOLARIS + llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt or README-solaris.txt for further information." << llendl; #else llwarns << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" @@ -1714,7 +1739,7 @@ void LLViewerWindow::initBase() LLRect notify_rect = full_window; //notify_rect.mTop -= 24; notify_rect.mBottom += STATUS_BAR_HEIGHT; - gNotifyBoxView = new LLNotifyBoxView("notify", notify_rect, FALSE, FOLLOWS_ALL); + gNotifyBoxView = new LLNotifyBoxView("notify_container", notify_rect, FALSE, FOLLOWS_ALL); mRootView->addChild(gNotifyBoxView, -2); // Tooltips go above floaters @@ -1819,117 +1844,117 @@ void LLViewerWindow::initWorldUI() S32 width = mRootView->getRect().getWidth(); LLRect full_window(0, height, width, 0); - LLRect bar_rect(-1, STATUS_BAR_HEIGHT, width+1, -1); - gToolBar = new LLToolBar("toolbar", bar_rect); + if ( gToolBar == NULL ) // Don't re-enter if objects are alreay created + { + LLRect bar_rect(-1, STATUS_BAR_HEIGHT, width+1, -1); + gToolBar = new LLToolBar("toolbar", bar_rect); - LLRect chat_bar_rect(-1,CHAT_BAR_HEIGHT, width+1, -1); - chat_bar_rect.translate(0, STATUS_BAR_HEIGHT-1); - gChatBar = new LLChatBar("chat", chat_bar_rect); + LLRect chat_bar_rect(-1,CHAT_BAR_HEIGHT, width+1, -1); + chat_bar_rect.translate(0, STATUS_BAR_HEIGHT-1); + gChatBar = new LLChatBar("chat", chat_bar_rect); - bar_rect.translate(0, STATUS_BAR_HEIGHT-1); - bar_rect.translate(0, CHAT_BAR_HEIGHT-1); - gOverlayBar = new LLOverlayBar("overlay", bar_rect); + bar_rect.translate(0, STATUS_BAR_HEIGHT-1); + bar_rect.translate(0, CHAT_BAR_HEIGHT-1); + gOverlayBar = new LLOverlayBar("overlay", bar_rect); - // panel containing chatbar, toolbar, and overlay, over floaters - LLRect bottom_rect(-1, 2*STATUS_BAR_HEIGHT + CHAT_BAR_HEIGHT, width+1, -1); - gBottomPanel = new LLBottomPanel("bottom panel", bottom_rect); + // panel containing chatbar, toolbar, and overlay, over floaters + LLRect bottom_rect(-1, 2*STATUS_BAR_HEIGHT + CHAT_BAR_HEIGHT, width+1, -1); + gBottomPanel = new LLBottomPanel("bottom panel", bottom_rect); - // the order here is important - gBottomPanel->addChild(gChatBar); - gBottomPanel->addChild(gToolBar); - gBottomPanel->addChild(gOverlayBar); - mRootView->addChild(gBottomPanel); + // the order here is important + gBottomPanel->addChild(gChatBar); + gBottomPanel->addChild(gToolBar); + gBottomPanel->addChild(gOverlayBar); + mRootView->addChild(gBottomPanel); - // View for hover information - gHoverView = new LLHoverView("gHoverView", full_window); - gHoverView->setVisible(TRUE); - mRootView->addChild(gHoverView); + // View for hover information + gHoverView = new LLHoverView("gHoverView", full_window); + gHoverView->setVisible(TRUE); + mRootView->addChild(gHoverView); - // - // Map - // - // TODO: Move instance management into class - gFloaterMap = new LLFloaterMap("Map"); - gFloaterMap->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); - gFloaterMap->setVisible( gSavedSettings.getBOOL("ShowMiniMap") ); + // + // Map + // + // TODO: Move instance management into class + gFloaterMap = new LLFloaterMap("Map"); + gFloaterMap->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); + gFloaterMap->setVisible( gSavedSettings.getBOOL("ShowMiniMap") ); - // keep onscreen - gFloaterView->adjustToFitScreen(gFloaterMap, FALSE); + // keep onscreen + gFloaterView->adjustToFitScreen(gFloaterMap, FALSE); - if (gSavedSettings.getBOOL("ShowCameraControls")) - { - LLFloaterCamera::show(NULL); - } - - if (gSavedSettings.getBOOL("ShowMovementControls")) - { - LLFloaterMove::show(NULL); - } - - // Must have one global chat floater so it can actually store - // the history. JC - gFloaterChat = new LLFloaterChat(); - gFloaterChat->setVisible( FALSE ); - - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) gFloaterChat->loadHistory(); + if (gSavedSettings.getBOOL("ShowCameraControls")) + { + LLFloaterCamera::show(NULL); + } + + if (gSavedSettings.getBOOL("ShowMovementControls")) + { + LLFloaterMove::show(NULL); + } + + gIMMgr = LLIMMgr::getInstance(); - gIMView = new LLIMView("gIMView", LLRect() ); - gIMView->setFollowsAll(); - mRootView->addChild(gIMView); + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) + { + LLFloaterChat::getInstance(LLSD())->loadHistory(); + } - LLRect morph_view_rect = full_window; - morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); - morph_view_rect.mTop = full_window.mTop - 32; - gMorphView = new LLMorphView("gMorphView", morph_view_rect ); - mRootView->addChild(gMorphView); - gMorphView->setVisible(FALSE); + LLRect morph_view_rect = full_window; + morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); + morph_view_rect.mTop = full_window.mTop - 32; + gMorphView = new LLMorphView("gMorphView", morph_view_rect ); + mRootView->addChild(gMorphView); + gMorphView->setVisible(FALSE); - gFloaterMute = new LLFloaterMute(); - gFloaterMute->setVisible(FALSE); + gFloaterMute = new LLFloaterMute(); + gFloaterMute->setVisible(FALSE); - LLWorldMapView::initClass(); + LLWorldMapView::initClass(); - LLRect world_map_rect = gSavedSettings.getRect("FloaterWorldMapRect"); - // if 0,0,0,0 then use fullscreen - if (world_map_rect.mTop == 0 - && world_map_rect.mLeft == 0 - && world_map_rect.mRight == 0 - && world_map_rect.mBottom == 0) - { - world_map_rect.set(0, height-TOOL_BAR_HEIGHT, width, STATUS_BAR_HEIGHT); - world_map_rect.stretch(-4); - gSavedSettings.setRect("FloaterWorldMapRect", world_map_rect); - } - gFloaterWorldMap = new LLFloaterWorldMap(); - gFloaterWorldMap->setVisible(FALSE); + LLRect world_map_rect = gSavedSettings.getRect("FloaterWorldMapRect"); + // if 0,0,0,0 then use fullscreen + if (world_map_rect.mTop == 0 + && world_map_rect.mLeft == 0 + && world_map_rect.mRight == 0 + && world_map_rect.mBottom == 0) + { + world_map_rect.set(0, height-TOOL_BAR_HEIGHT, width, STATUS_BAR_HEIGHT); + world_map_rect.stretch(-4); + gSavedSettings.setRect("FloaterWorldMapRect", world_map_rect); + } + gFloaterWorldMap = new LLFloaterWorldMap(); + gFloaterWorldMap->setVisible(FALSE); - // - // Tools for building - // + // + // Tools for building + // - // Toolbox floater - init_menus(); + // Toolbox floater + init_menus(); - gFloaterTools = new LLFloaterTools(); - gFloaterTools->setVisible(FALSE); + gFloaterTools = new LLFloaterTools(); + gFloaterTools->setVisible(FALSE); - // Status bar - S32 menu_bar_height = gMenuBarView->getRect().getHeight(); - LLRect root_rect = gViewerWindow->getRootView()->getRect(); - LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); - gStatusBar = new LLStatusBar("status", status_rect); - gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + // Status bar + S32 menu_bar_height = gMenuBarView->getRect().getHeight(); + LLRect root_rect = gViewerWindow->getRootView()->getRect(); + LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); + gStatusBar = new LLStatusBar("status", status_rect); + gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); - gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); - gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); - // sync bg color with menu bar - gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); + gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); + gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); + // sync bg color with menu bar + gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); + LLFloaterChatterBox::createInstance(LLSD()); - gViewerWindow->getRootView()->addChild(gStatusBar); + gViewerWindow->getRootView()->addChild(gStatusBar); - // menu holder appears on top to get first pass at all mouse events - gViewerWindow->getRootView()->sendChildToFront(gMenuHolder); + // menu holder appears on top to get first pass at all mouse events + gViewerWindow->getRootView()->sendChildToFront(gMenuHolder); + } } @@ -1953,13 +1978,12 @@ LLViewerWindow::~LLViewerWindow() gFloaterTools = NULL; gStatusBar = NULL; gFloaterCamera = NULL; - gIMView = NULL; + gIMMgr = NULL; gHoverView = NULL; gFloaterView = NULL; gMorphView = NULL; - gFloaterChat = NULL; gFloaterMute = NULL; gFloaterMap = NULL; @@ -2150,6 +2174,23 @@ void LLViewerWindow::reshape(S32 width, S32 height) } } + +// Hide normal UI when a logon fails +void LLViewerWindow::setNormalControlsVisible( BOOL visible ) +{ + if ( gBottomPanel ) + gBottomPanel->setVisible( visible ); + + if ( gMenuBarView ) + gMenuBarView->setVisible( visible ); + + if ( gStatusBar ) + gStatusBar->setVisible( visible ); +} + + + + void LLViewerWindow::drawDebugText() { mDebugText->draw(); @@ -2703,16 +2744,29 @@ BOOL LLViewerWindow::handlePerFrameHover() } } + gPipeline.sRenderProcessBeacons = FALSE; + KEY key = gKeyboard->currentKey(); + if (((mask & MASK_CONTROL) && ('N' == key || 'n' == key)) || (gFloaterTools && gFloaterTools->getVisible()) || gSavedSettings.getBOOL("BeaconAlwaysOn")) + { + gPipeline.sRenderProcessBeacons = TRUE; + } + +/* // Show joints while in edit mode and hold down alt key. if (gHUDManager) { - if (gSavedSettings.getBOOL("AltShowsPhysical") + BOOL menuOption = gSavedSettings.getBOOL("AltShowsPhysical"); + if (menuOption || (gFloaterTools && gFloaterTools->getVisible())) { gHUDManager->toggleShowPhysical( mask & MASK_ALT ); } + else + { + gHUDManager->toggleShowPhysical( FALSE ); + } } - +*/ BOOL handled = FALSE; BOOL handled_by_top_ctrl = FALSE; @@ -4143,11 +4197,15 @@ void LLViewerWindow::saveMovieNumbered(void*) S32 y = gViewerWindow->getWindowHeight(); gbCapturing = TRUE; +#if !LL_SOLARIS gMovieMaker.StartCapture((char *)filepath.c_str(), x, y); +#endif } else { +#if !LL_SOLARIS gMovieMaker.EndCapture(); +#endif gbCapturing = FALSE; } } diff --git a/linden/indra/newview/llviewerwindow.h b/linden/indra/newview/llviewerwindow.h index e6a9a14..4560427 100644 --- a/linden/indra/newview/llviewerwindow.h +++ b/linden/indra/newview/llviewerwindow.h @@ -85,6 +85,8 @@ public: /*virtual*/ void handleQuit(LLWindow *window); /*virtual*/ BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ void handleMouseLeave(LLWindow *window); /*virtual*/ void handleResize(LLWindow *window, S32 x, S32 y); @@ -174,6 +176,9 @@ public: BOOL handleKey(KEY key, MASK mask); void handleScrollWheel (S32 clicks); + // Hide normal UI when a logon fails, re-show everything when logon is attempted again + void setNormalControlsVisible( BOOL visible ); + // Handle the application becoming active (frontmost) or inactive //BOOL handleActivate(BOOL activate); diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index a375d84..3b9e8ea 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp @@ -116,6 +116,12 @@ //#include "vtune/vtuneapi.h" +//Ventrella +#include "llgesturemgr.h" //needed to trigger the voice gestculations +#include "llvoicevisualizer.h" +#include "llvoiceclient.h" +//end Ventrella + // Direct imports, evil extern LLSky gSky; extern void set_avatar_character(void* charNameArg); @@ -147,9 +153,7 @@ const F32 PELVIS_LAG_WALKING = 0.4f; // ...while walking const F32 PELVIS_LAG_MOUSELOOK = 0.15f; const F32 MOUSELOOK_PELVIS_FOLLOW_FACTOR = 0.5f; -//Ventrella const F32 PELVIS_LAG_WHEN_FOLLOW_CAM_IS_ON = 0.0001f; // not zero! - something gets divided by this! -//end Ventrella #define PELVIS_ROT_THRESHOLD_SLOW 60.0f // amount of deviation allowed between #define PELVIS_ROT_THRESHOLD_FAST 2.0f // the pelvis and the view direction @@ -221,10 +225,6 @@ const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; const S32 MAX_BUBBLES = 7; - -const bool USING_VENTRELLA_AVATAR_MOTION_TEST = false; - - S32 LLVOAvatar::sMaxVisible = 50; LLVOAvatar::ETextureIndex LLVOAvatar::sBakedTextureIndices[BAKED_TEXTURE_COUNT] = @@ -455,121 +455,16 @@ public: // called after parameters have been set // must return true to indicate success and be available for activation virtual LLMotionInitStatus onInitialize(LLCharacter *character) - { - //Ventrella - // I'm replacing the code below because I need to change - // the logic in order to add other body parts - /* + { mCharacter = character; - - if (!mChestState.setJoint( character->getJoint("mChest"))) - { - return STATUS_FAILURE; - } - - mChestState.setUsage(LLJointState::ROT); - - addJointState( &mChestState ); - return STATUS_SUCCESS; - */ - - bool success = true; if ( !mChestState.setJoint( character->getJoint( "mChest" ) ) ) { success = false; } - if ( USING_VENTRELLA_AVATAR_MOTION_TEST ) - { - if ( !mNeckState.setJoint ( character->getJoint( "mNeck" )) ) { success = false; } - - if ( !mCollarLeftState.setJoint ( character->getJoint( "mCollarLeft" )) ) { success = false; } - if ( !mShoulderLeftState.setJoint ( character->getJoint( "mShoulderLeft" )) ) { success = false; } - if ( !mElbowLeftState.setJoint ( character->getJoint( "mElbowLeft" )) ) { success = false; } - if ( !mWristLeftState.setJoint ( character->getJoint( "mWristLeft" )) ) { success = false; } - - if ( !mCollarRightState.setJoint ( character->getJoint( "mCollarRight" )) ) { success = false; } - if ( !mShoulderRightState.setJoint ( character->getJoint( "mShoulderRight" )) ) { success = false; } - if ( !mElbowRightState.setJoint ( character->getJoint( "mElbowRight" )) ) { success = false; } - if ( !mWristRightState.setJoint ( character->getJoint( "mWristRight" )) ) { success = false; } - - if ( !mHipLeftState.setJoint ( character->getJoint( "mHipLeft" )) ) { success = false; } - if ( !mKneeLeftState.setJoint ( character->getJoint( "mKneeLeft" )) ) { success = false; } - if ( !mAnkleLeftState.setJoint ( character->getJoint( "mAnkleLeft" )) ) { success = false; } - - if ( !mHipRightState.setJoint ( character->getJoint( "mHipRight" )) ) { success = false; } - if ( !mKneeRightState.setJoint ( character->getJoint( "mKneeRight" )) ) { success = false; } - if ( !mAnkleRightState.setJoint ( character->getJoint( "mAnkleRight" )) ) { success = false; } - } - if ( success ) { mChestState.setUsage(LLJointState::ROT); addJointState( &mChestState ); - - if ( USING_VENTRELLA_AVATAR_MOTION_TEST ) - { - //------------------------------------------- - // neck - //------------------------------------------- - mNeckState.setUsage(LLJointState::ROT); - addJointState( &mNeckState ); - - //------------------------------------------- - // left arm - //------------------------------------------- - mCollarLeftState.setUsage(LLJointState::ROT); - addJointState( &mCollarLeftState ); - - mShoulderLeftState.setUsage(LLJointState::ROT); - addJointState( &mShoulderLeftState ); - - mElbowLeftState.setUsage(LLJointState::ROT); - addJointState( &mElbowLeftState ); - - mWristLeftState.setUsage(LLJointState::ROT); - addJointState( &mWristLeftState ); - - - //------------------------------------------- - // right arm - //------------------------------------------- - mCollarRightState.setUsage(LLJointState::ROT); - addJointState( &mCollarRightState ); - - mShoulderRightState.setUsage(LLJointState::ROT); - addJointState( &mShoulderRightState ); - - mElbowRightState.setUsage(LLJointState::ROT); - addJointState( &mElbowRightState ); - - mWristRightState.setUsage(LLJointState::ROT); - addJointState( &mWristRightState ); - - //------------------------------------------- - // left leg - //------------------------------------------- - mHipLeftState.setUsage(LLJointState::ROT); - addJointState( &mHipLeftState ); - - mKneeLeftState.setUsage(LLJointState::ROT); - addJointState( &mKneeLeftState ); - - mAnkleLeftState.setUsage(LLJointState::ROT); - addJointState( &mAnkleLeftState ); - - - //------------------------------------------- - // right leg - //------------------------------------------- - mHipRightState.setUsage(LLJointState::ROT); - addJointState( &mHipRightState ); - - mKneeRightState.setUsage(LLJointState::ROT); - addJointState( &mKneeRightState ); - - mAnkleRightState.setUsage(LLJointState::ROT); - addJointState( &mAnkleRightState ); - } } if ( success ) @@ -580,7 +475,6 @@ public: { return STATUS_FAILURE; } - //end Ventrella } // called when a motion is activated @@ -599,37 +493,9 @@ public: mChestState.setRotation(LLQuaternion(breathe_amt, LLVector3(0.f, 1.f, 0.f))); - //Ventrella - if ( USING_VENTRELLA_AVATAR_MOTION_TEST ) - { - F32 wave = ( sinf ( time * 2.0f ) * 0.5f ); - - mChestState.setRotation ( LLQuaternion( wave, LLVector3( -1.0f, 0.0f, 0.0f ) ) ); - - mCollarLeftState.setRotation ( LLQuaternion( wave, LLVector3( 1.0f, 0.0f, 0.0f ) ) ); - mShoulderLeftState.setRotation ( LLQuaternion( wave, LLVector3( 1.0f, 0.0f, 0.0f ) ) ); - mElbowLeftState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, 0.0f, 1.0f ) ) ); - mWristLeftState.setRotation ( LLQuaternion( wave, LLVector3( 1.0f, 0.0f, 0.0f ) ) ); - - mCollarRightState.setRotation ( LLQuaternion( wave, LLVector3( -1.0f, 0.0f, 0.0f ) ) ); - mShoulderRightState.setRotation ( LLQuaternion( wave, LLVector3( 1.0f, 0.0f, 0.0f ) ) ); - mElbowRightState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, 0.0f, 1.0f ) ) ); - mWristRightState.setRotation ( LLQuaternion( wave, LLVector3( 1.0f, 0.0f, 0.0f ) ) ); - - mHipLeftState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, 1.0f, 0.0f ) ) ); - mKneeLeftState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, -1.0f, 0.0f ) ) ); - mAnkleLeftState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, 1.0f, 0.0f ) ) ); - - mHipRightState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, 1.0f, 0.0f ) ) ); - mKneeRightState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, -1.0f, 0.0f ) ) ); - mAnkleRightState.setRotation ( LLQuaternion( wave, LLVector3( 0.0f, 1.0f, 0.0f ) ) ); - } - //end Ventrella - return TRUE; } - // called when a motion is deactivated virtual void onDeactivate() {} @@ -637,26 +503,7 @@ public: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- - LLJointState mChestState; - - //Ventrella - LLJointState mNeckState; - LLJointState mCollarLeftState; - LLJointState mShoulderLeftState; - LLJointState mElbowLeftState; - LLJointState mWristLeftState; - LLJointState mCollarRightState; - LLJointState mShoulderRightState; - LLJointState mElbowRightState; - LLJointState mWristRightState; - LLJointState mHipLeftState; - LLJointState mKneeLeftState; - LLJointState mAnkleLeftState; - LLJointState mHipRightState; - LLJointState mKneeRightState; - LLJointState mAnkleRightState; - //end Ventrella - + LLJointState mChestState; F32 mBreatheRate; LLCharacter* mCharacter; }; @@ -819,6 +666,10 @@ LLVOAvatar::LLVOAvatar( LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune + + // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline + bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job + mVoiceVisualizer = ( LLVoiceVisualizer *)gHUDManager->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; @@ -1069,9 +920,13 @@ LLVOAvatar::LLVOAvatar( createMotion( ANIM_AGENT_CUSTOMIZE_DONE); //VTPause(); // VTune + + //Ventrella + mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) ); + mCurrentGesticulationLevel = 0; + //END Ventrella } - //------------------------------------------------------------------------ // LLVOAvatar::~LLVOAvatar() //------------------------------------------------------------------------ @@ -1143,6 +998,8 @@ void LLVOAvatar::markDead() sNumVisibleChatBubbles--; } + mVoiceVisualizer->markDead(); + mBeam = NULL; LLViewerObject::markDead(); } @@ -2459,7 +2316,84 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) updateCharacter(agent); + //Ventrella + bool voiceEnabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel(); + // disable voice visualizer when in mouselook + mVoiceVisualizer->setVoiceEnabled( voiceEnabled && !(mIsSelf && gAgent.cameraMouselook()) ); + if ( voiceEnabled ) + { + //---------------------------------------------------------------- + // Only do gesture triggering for your own avatar, and only when you're in a proximal channel. + //---------------------------------------------------------------- + if( mIsSelf ) + { + //---------------------------------------------------------------------------------------- + // The following takes the voice signal and uses that to trigger gesticulations. + //---------------------------------------------------------------------------------------- + int lastGesticulationLevel = mCurrentGesticulationLevel; + mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel(); + + //--------------------------------------------------------------------------------------------------- + // If "current gesticulation level" changes, we catch this, and trigger the new gesture + //--------------------------------------------------------------------------------------------------- + if ( lastGesticulationLevel != mCurrentGesticulationLevel ) + { + if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF ) + { + LLString gestureString = "unInitialized"; + if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; } + else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; } + else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; } + else { printf( "oops - CurrentGesticulationLevel can be only 0, 1, or 2\n" ); } + + // this is the call that Karl S. created for triggering gestures from within the code. + gGestureManager.triggerAndReviseString( gestureString ); + } + } + + } //if( mIsSelf ) + + //----------------------------------------------------------------------------------------------------------------- + // If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer. + // Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol. + // + // Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been + // "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking. + //----------------------------------------------------------------------------------------------------------------- + if ( gVoiceClient->getIsSpeaking( mID ) ) + { + if ( ! mVoiceVisualizer->getCurrentlySpeaking() ) + { + mVoiceVisualizer->setStartSpeaking(); + + //printf( "gAwayTimer.reset();\n" ); + } + + mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) ); + + if( mIsSelf ) + { + gAgent.clearAFK(); + } + } + else + { + if ( mVoiceVisualizer->getCurrentlySpeaking() ) + { + mVoiceVisualizer->setStopSpeaking(); + } + } + + //-------------------------------------------------------------------------------------------- + // here we get the approximate head position and set as sound source for the voice symbol + // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) + //-------------------------------------------------------------------------------------------- + LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); + mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); + }//if ( voiceEnabled ) + //End Ventrella + if (LLVOAvatar::sJointDebug) { @@ -2469,7 +2403,6 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) LLJoint::sNumUpdates = 0; LLJoint::sNumTouches = 0; - if (gNoRender) { return TRUE; @@ -3272,14 +3205,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV ); F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, PELVIS_ROT_THRESHOLD_SLOW, PELVIS_ROT_THRESHOLD_FAST); - - //Ventrella - //if ( gAgent.getCameraMode() == CAMERA_MODE_FOLLOW ) - //{ - // pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, 1.0f, 1.0f); - //} - //end Ventrella - + if (self_in_mouselook) { pelvis_rot_threshold *= MOUSELOOK_PELVIS_FOLLOW_FACTOR; @@ -3357,13 +3283,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) pelvis_lag_time = PELVIS_LAG_WALKING; } - //Ventrella - //if ( gAgent.getCameraMode() == CAMERA_MODE_FOLLOW ) - //{ - // pelvis_lag_time = PELVIS_LAG_WHEN_FOLLOW_CAM_IS_ON; - //} - //end Ventrella - F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) ); @@ -3481,13 +3400,13 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) // AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); - F32 gain = gSavedSettings.getF32("AudioLevelFootsteps"); + F32 gain = .30f * gSavedSettings.getF32("AudioLevelAmbient"); LLUUID& step_sound_id = getStepSound(); LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); if (gParcelMgr && gParcelMgr->canHearSound(foot_pos_global) - && gMuteListp && !gMuteListp->isMuted(getID())) + && gMuteListp && !gMuteListp->isMuted(getID(), LLMute::flagObjectSounds)) { gAudiop->triggerSound(step_sound_id, getID(), gain, foot_pos_global); } @@ -3496,6 +3415,32 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) mRoot.updateWorldMatrixChildren(); + // Send the speaker position to the spatialized voice system. + if(mIsSelf) + { + LLMatrix3 rot; + LLVector3d pos; +#if 1 + // character rotation (stable, shouldn't move with animations) + rot = mRoot.getWorldRotation().getMatrix3(); +#else + // actual head rotation (moves with animations, probably a bit too much) + rot.setRows( + LLVector3::x_axis * mSkullp->getWorldRotation(), + LLVector3::y_axis * mSkullp->getWorldRotation(), + LLVector3::z_axis * mSkullp->getWorldRotation()); +#endif + + pos = getPositionGlobal(); + pos += LLVector3d(mHeadOffset); + + // MBW -- XXX -- Setting velocity to 0 for now. May figure it out later... + gVoiceClient->setAvatarPosition( + pos, // position + LLVector3::zero, // velocity + rot); // rotation matrix + } + if (!mDebugText.size() && mText.notNull()) { mText->markDead(); @@ -4203,7 +4148,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent) if( render_avatar ) { - mShadowImagep->addTextureStats(mPixelArea, 1.f); + mShadowImagep->addTextureStats(mPixelArea); } } @@ -4418,18 +4363,20 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { LLVector3d char_pos_global = gAgent.getPosGlobalFromAgent(getCharacterPosition()); if (gParcelMgr && gParcelMgr->canHearSound(char_pos_global) - && gMuteListp && !gMuteListp->isMuted(getID())) + && gMuteListp && !gMuteListp->isMuted(getID(), LLMute::flagObjectSounds)) { // RN: uncomment this to play on typing sound at fixed volume once sound engine is fixed // to support both spatialized and non-spatialized instances of the same sound //if (mIsSelf) //{ - // gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), 0.8f); + // F32 volume = gain * gSavedSettings.getF32("AudioLevelUI") + // gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), volume); //} //else { LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping")); - gAudiop->triggerSound(sound_id, getID(), 1.f, char_pos_global); + F32 volume = gSavedSettings.getF32("AudioLevelSFX"); + gAudiop->triggerSound(sound_id, getID(), volume, char_pos_global); } } } @@ -4818,7 +4765,6 @@ LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) return (LLJoint*)&mSkeleton[num]; } - //----------------------------------------------------------------------------- // requestStopMotion() //----------------------------------------------------------------------------- @@ -5810,7 +5756,7 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) { LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); - if (!attachment->addObject(viewer_object)) + if (!attachment || !attachment->addObject(viewer_object)) { return FALSE; } diff --git a/linden/indra/newview/llvoavatar.h b/linden/indra/newview/llvoavatar.h index 427293a..5b92445 100644 --- a/linden/indra/newview/llvoavatar.h +++ b/linden/indra/newview/llvoavatar.h @@ -52,6 +52,11 @@ #include "llxmltree.h" #include "llwearable.h" +//Ventrella +//#include "llvoiceclient.h" +#include "llvoicevisualizer.h" +//End Ventrella + const S32 VOAVATAR_SCRATCH_TEX_WIDTH = 512; const S32 VOAVATAR_SCRATCH_TEX_HEIGHT = 512; @@ -947,6 +952,17 @@ protected: LLTexLayerSet* getLayerSet(ETextureIndex index) const; LLHost getObjectHost() const; S32 getLocalDiscardLevel( S32 index); + +//Ventrella + //----------------------------------------------------------------------------------------------- + // the Voice Visualizer is responsible for detecting the user's voice signal, and when the + // user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations + //----------------------------------------------------------------------------------------------- + private: + LLVoiceVisualizer * mVoiceVisualizer; + int mCurrentGesticulationLevel; +//End Ventrella + }; #endif // LL_VO_AVATAR_H diff --git a/linden/indra/newview/llvocache.cpp b/linden/indra/newview/llvocache.cpp index f249c87..2b3569d 100644 --- a/linden/indra/newview/llvocache.cpp +++ b/linden/indra/newview/llvocache.cpp @@ -60,16 +60,25 @@ LLVOCacheEntry::LLVOCacheEntry() } +static inline void checkedRead(FILE *fp, void *data, size_t nbytes) +{ + if (fread(data, 1, nbytes, fp) != nbytes) + { + llwarns << "Short read" << llendl; + memset(data, 0, nbytes); + } +} + LLVOCacheEntry::LLVOCacheEntry(FILE *fp) { S32 size; - fread(&mLocalID, 1, sizeof(U32), fp); - fread(&mCRC, 1, sizeof(U32), fp); - fread(&mHitCount, 1, sizeof(S32), fp); - fread(&mDupeCount, 1, sizeof(S32), fp); - fread(&mCRCChangeCount, 1, sizeof(S32), fp); + checkedRead(fp, &mLocalID, sizeof(U32)); + checkedRead(fp, &mCRC, sizeof(U32)); + checkedRead(fp, &mHitCount, sizeof(S32)); + checkedRead(fp, &mDupeCount, sizeof(S32)); + checkedRead(fp, &mCRCChangeCount, sizeof(S32)); - fread(&size, 1, sizeof(S32), fp); + checkedRead(fp, &size, sizeof(S32)); // Corruption in the cache entries if ((size > 10000) || (size < 1)) @@ -85,7 +94,7 @@ LLVOCacheEntry::LLVOCacheEntry(FILE *fp) } mBuffer = new U8[size]; - fread(mBuffer, 1, size, fp); + checkedRead(fp, mBuffer, size); mDP.assignBuffer(mBuffer, size); } @@ -141,14 +150,22 @@ void LLVOCacheEntry::dump() const << llendl; } +static inline void checkedWrite(FILE *fp, const void *data, size_t nbytes) +{ + if (fwrite(data, 1, nbytes, fp) != nbytes) + { + llwarns << "Short write" << llendl; + } +} + void LLVOCacheEntry::writeToFile(FILE *fp) const { - fwrite(&mLocalID, 1, sizeof(U32), fp); - fwrite(&mCRC, 1, sizeof(U32), fp); - fwrite(&mHitCount, 1, sizeof(S32), fp); - fwrite(&mDupeCount, 1, sizeof(S32), fp); - fwrite(&mCRCChangeCount, 1, sizeof(S32), fp); + checkedWrite(fp, &mLocalID, sizeof(U32)); + checkedWrite(fp, &mCRC, sizeof(U32)); + checkedWrite(fp, &mHitCount, sizeof(S32)); + checkedWrite(fp, &mDupeCount, sizeof(S32)); + checkedWrite(fp, &mCRCChangeCount, sizeof(S32)); S32 size = mDP.getBufferSize(); - fwrite(&size, 1, sizeof(S32), fp); - fwrite(mBuffer, 1, size, fp); + checkedWrite(fp, &size, sizeof(S32)); + checkedWrite(fp, mBuffer, size); } diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index 5d9c581..4725b33 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp @@ -336,16 +336,13 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent) // BUG could speed this up by caching the relative_position and range calculations void LLVOGrass::updateTextures(LLAgent &agent) { - F32 texel_area_ratio = 1.f; - F32 cos_angle = 1.f; - if (getTEImage(0)) { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); } - getTEImage(0)->addTextureStats(mPixelArea, texel_area_ratio, cos_angle); + getTEImage(0)->addTextureStats(mPixelArea); } } @@ -442,7 +439,8 @@ void LLVOGrass::getGeometry(S32 idx, LLStrider& indicesp) { mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); - mLastPatchUpdateTime = mPatch->getLastUpdateTime(); + if (mPatch) + mLastPatchUpdateTime = mPatch->getLastUpdateTime(); LLVector3 position; // Create random blades of grass with gaussian distribution diff --git a/linden/indra/newview/llvoiceclient.cpp b/linden/indra/newview/llvoiceclient.cpp new file mode 100644 index 0000000..0bc42c6 --- /dev/null +++ b/linden/indra/newview/llvoiceclient.cpp @@ -0,0 +1,4076 @@ +/** + * @file llvoiceclient.cpp + * @brief Implementation of LLVoiceClient class which is the interface to the voice client process. + * + * Copyright (c) 2001-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include + +#include "llviewerprecompiledheaders.h" +#include "llvoiceclient.h" + +#include "llsdutil.h" + +#include "llvoavatar.h" +#include "llbufferstream.h" +#include "llfile.h" +#include "expat/expat.h" +#include "llcallbacklist.h" +#include "llviewerregion.h" +#include "llviewernetwork.h" // for gUserServerChoice +#include "llfloateractivespeakers.h" // for LLSpeakerMgr +#include "llbase64.h" +#include "llviewercontrol.h" +#include "llkeyboard.h" +#include "viewer.h" // for gDisconnected, gDisableVoice +#include "llmutelist.h" // to check for muted avatars +#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" + +// for base64 decoding +#include "apr-1/apr_base64.h" + +// for SHA1 hash +#include "apr-1/apr_sha1.h" + +// If we are connecting to agni AND the user's last name is "Linden", join this channel instead of looking up the sim name. +// If we are connecting to agni and the user's last name is NOT "Linden", disable voice. +#define AGNI_LINDENS_ONLY_CHANNEL "SL" +static bool sConnectingToAgni = false; +F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f; + +const F32 SPEAKING_TIMEOUT = 1.f; + +const int VOICE_MAJOR_VERSION = 1; +const int VOICE_MINOR_VERSION = 0; + +LLVoiceClient *gVoiceClient = NULL; + +// Don't retry connecting to the daemon more frequently than this: +const F32 CONNECT_THROTTLE_SECONDS = 1.0f; + +// Don't send positional updates more frequently than this: +const F32 UPDATE_THROTTLE_SECONDS = 0.1f; + +const F32 LOGIN_RETRY_SECONDS = 10.0f; +const int MAX_LOGIN_RETRIES = 12; + +class LLViewerVoiceAccountProvisionResponder : + public LLHTTPClient::Responder +{ +public: + LLViewerVoiceAccountProvisionResponder(int retries) + { + mRetries = retries; + } + + virtual void error(U32 status, const std::string& reason) + { + if ( mRetries > 0 ) + { + if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision( + mRetries - 1); + } + else + { + //TODO: throw an error message? + if ( gVoiceClient ) gVoiceClient->giveUp(); + } + } + + virtual void result(const LLSD& content) + { + if ( gVoiceClient ) + { + gVoiceClient->login( + content["username"].asString(), + content["password"].asString()); + } + } + +private: + int mRetries; +}; + +/** + * @class LLVivoxProtocolParser + * @brief This class helps construct new LLIOPipe specializations + * @see LLIOPipe + * + * THOROUGH_DESCRIPTION + */ +class LLVivoxProtocolParser : public LLIOPipe +{ + LOG_CLASS(LLVivoxProtocolParser); +public: + LLVivoxProtocolParser(); + virtual ~LLVivoxProtocolParser(); + +protected: + /* @name LLIOPipe virtual implementations + */ + //@{ + /** + * @brief Process the data in buffer + */ + virtual EStatus process_impl( + const LLChannelDescriptors& channels, + buffer_ptr_t& buffer, + bool& eos, + LLSD& context, + LLPumpIO* pump); + //@} + + std::string mInput; + + // Expat control members + XML_Parser parser; + int responseDepth; + bool ignoringTags; + bool isEvent; + int ignoreDepth; + + // Members for processing responses. The values are transient and only valid within a call to processResponse(). + int returnCode; + int statusCode; + std::string statusString; + std::string uuidString; + std::string actionString; + std::string connectorHandle; + std::string accountHandle; + std::string sessionHandle; + std::string eventSessionHandle; + + // Members for processing events. The values are transient and only valid within a call to processResponse(). + std::string eventTypeString; + int state; + std::string uriString; + bool isChannel; + std::string nameString; + std::string audioMediaString; + std::string displayNameString; + int participantType; + bool isLocallyMuted; + bool isModeratorMuted; + bool isSpeaking; + int volume; + F32 energy; + + // Members for processing text between tags + std::string textBuffer; + bool accumulateText; + + void reset(); + + void processResponse(std::string tag); + +static void XMLCALL ExpatStartTag(void *data, const char *el, const char **attr); +static void XMLCALL ExpatEndTag(void *data, const char *el); +static void XMLCALL ExpatCharHandler(void *data, const XML_Char *s, int len); + + void StartTag(const char *tag, const char **attr); + void EndTag(const char *tag); + void CharData(const char *buffer, int length); + +}; + +LLVivoxProtocolParser::LLVivoxProtocolParser() +{ + parser = NULL; + parser = XML_ParserCreate(NULL); + + reset(); +} + +void LLVivoxProtocolParser::reset() +{ + responseDepth = 0; + ignoringTags = false; + accumulateText = false; + textBuffer.clear(); +} + +//virtual +LLVivoxProtocolParser::~LLVivoxProtocolParser() +{ + if (parser) + XML_ParserFree(parser); +} + +// virtual +LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( + const LLChannelDescriptors& channels, + buffer_ptr_t& buffer, + bool& eos, + LLSD& context, + LLPumpIO* pump) +{ + LLBufferStream istr(channels, buffer.get()); + std::ostringstream ostr; + while (istr.good()) + { + char buf[1024]; + istr.read(buf, sizeof(buf)); + mInput.append(buf, istr.gcount()); + } + + // MBW -- XXX -- This should no longer be necessary. Or even possible. + // We've read all the data out of the buffer. Make sure it doesn't accumulate. +// buffer->clear(); + + // Look for input delimiter(s) in the input buffer. If one is found, send the message to the xml parser. + int start = 0; + int delim; + while((delim = mInput.find("\n\n\n", start)) != std::string::npos) + { + // Turn this on to log incoming XML + if(0) + { + int foo = mInput.find("Set3DPosition", start); + int bar = mInput.find("ParticipantPropertiesEvent", start); + if(foo != std::string::npos && (foo < delim)) + { + // This is a Set3DPosition response. Don't print it, since these are way too spammy. + } + else if(bar != std::string::npos && (bar < delim)) + { + // This is a ParticipantPropertiesEvent response. Don't print it, since these are way too spammy. + } + else + { + llinfos << "parsing: " << mInput.substr(start, delim - start) << llendl; + } + } + + // Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser) + reset(); + + XML_ParserReset(parser, NULL); + XML_SetElementHandler(parser, ExpatStartTag, ExpatEndTag); + XML_SetCharacterDataHandler(parser, ExpatCharHandler); + XML_SetUserData(parser, this); + XML_Parse(parser, mInput.data() + start, delim - start, false); + + start = delim + 3; + } + + if(start != 0) + mInput = mInput.substr(start); + +// llinfos << "at end, mInput is: " << mInput << llendl; + + if(!gVoiceClient->mConnected) + { + // If voice has been disabled, we just want to close the socket. This does so. + llinfos << "returning STATUS_STOP" << llendl; + return STATUS_STOP; + } + + return STATUS_OK; +} + +void XMLCALL LLVivoxProtocolParser::ExpatStartTag(void *data, const char *el, const char **attr) +{ + if (data) + { + LLVivoxProtocolParser *object = (LLVivoxProtocolParser*)data; + object->StartTag(el, attr); + } +} + +// -------------------------------------------------------------------------------- + +void XMLCALL LLVivoxProtocolParser::ExpatEndTag(void *data, const char *el) +{ + if (data) + { + LLVivoxProtocolParser *object = (LLVivoxProtocolParser*)data; + object->EndTag(el); + } +} + +// -------------------------------------------------------------------------------- + +void XMLCALL LLVivoxProtocolParser::ExpatCharHandler(void *data, const XML_Char *s, int len) +{ + if (data) + { + LLVivoxProtocolParser *object = (LLVivoxProtocolParser*)data; + object->CharData(s, len); + } +} + +// -------------------------------------------------------------------------------- + + +void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) +{ + // Reset the text accumulator. We shouldn't have strings that are inturrupted by new tags + textBuffer.clear(); + // only accumulate text if we're not ignoring tags. + accumulateText = !ignoringTags; + + if (responseDepth == 0) + { + isEvent = strcmp("Event", tag) == 0; + + if (strcmp("Response", tag) == 0 || isEvent) + { + // Grab the attributes + while (*attr) + { + const char *key = *attr++; + const char *value = *attr++; + + if (strcmp("requestId", key) == 0) + { + uuidString = value; + } + else if (strcmp("action", key) == 0) + { + actionString = value; + } + else if (strcmp("type", key) == 0) + { + eventTypeString = value; + } + } + } + //llinfos << tag << " (" << responseDepth << ")" << llendl; + } + else + { + if (ignoringTags) + { + //llinfos << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << llendl; + } + else + { + //llinfos << tag << " (" << responseDepth << ")" << llendl; + + // Ignore the InputXml stuff so we don't get confused + if (strcmp("InputXml", tag) == 0) + { + ignoringTags = true; + ignoreDepth = responseDepth; + accumulateText = false; + + //llinfos << "starting ignore, ignoreDepth is " << ignoreDepth << llendl; + } + else if (strcmp("CaptureDevices", tag) == 0) + { + gVoiceClient->clearCaptureDevices(); + } + else if (strcmp("RenderDevices", tag) == 0) + { + gVoiceClient->clearRenderDevices(); + } + } + } + responseDepth++; +} + +// -------------------------------------------------------------------------------- + +void LLVivoxProtocolParser::EndTag(const char *tag) +{ + const char *string = textBuffer.c_str(); + bool clearbuffer = true; + + responseDepth--; + + if (ignoringTags) + { + if (ignoreDepth == responseDepth) + { + //llinfos << "end of ignore" << llendl; + ignoringTags = false; + } + else + { + //llinfos << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << llendl; + } + } + + if (!ignoringTags) + { + //llinfos << "processing tag " << tag << " (depth = " << responseDepth << ")" << llendl; + + // Closing a tag. Finalize the text we've accumulated and reset + if (strcmp("ReturnCode", tag) == 0) + returnCode = strtol(string, NULL, 10); + else if (strcmp("StatusCode", tag) == 0) + statusCode = strtol(string, NULL, 10); + else if (strcmp("ConnectorHandle", tag) == 0) + connectorHandle = string; + else if (strcmp("AccountHandle", tag) == 0) + accountHandle = string; + else if (strcmp("SessionHandle", tag) == 0) + { + if (isEvent) + eventSessionHandle = string; + else + sessionHandle = string; + } + else if (strcmp("StatusString", tag) == 0) + statusString = string; + else if (strcmp("State", tag) == 0) + state = strtol(string, NULL, 10); + else if (strcmp("URI", tag) == 0) + uriString = string; + else if (strcmp("IsChannel", tag) == 0) + isChannel = strcmp(string, "true") == 0; + else if (strcmp("Name", tag) == 0) + nameString = string; + else if (strcmp("AudioMedia", tag) == 0) + audioMediaString = string; + else if (strcmp("ChannelName", tag) == 0) + nameString = string; + else if (strcmp("ParticipantURI", tag) == 0) + uriString = string; + else if (strcmp("DisplayName", tag) == 0) + displayNameString = string; + else if (strcmp("AccountName", tag) == 0) + nameString = string; + else if (strcmp("ParticipantTyppe", tag) == 0) + participantType = strtol(string, NULL, 10); + else if (strcmp("IsLocallyMuted", tag) == 0) + isLocallyMuted = strcmp(string, "true") == 0; + else if (strcmp("IsModeratorMuted", tag) == 0) + isModeratorMuted = strcmp(string, "true") == 0; + else if (strcmp("IsSpeaking", tag) == 0) + isSpeaking = strcmp(string, "true") == 0; + else if (strcmp("Volume", tag) == 0) + volume = strtol(string, NULL, 10); + else if (strcmp("Energy", tag) == 0) + energy = (F32)strtod(string, NULL); + else if (strcmp("MicEnergy", tag) == 0) + energy = (F32)strtod(string, NULL); + else if (strcmp("ChannelName", tag) == 0) + nameString = string; + else if (strcmp("ChannelURI", tag) == 0) + uriString = string; + else if (strcmp("ChannelListResult", tag) == 0) + { + gVoiceClient->addChannelMapEntry(nameString, uriString); + } + else if (strcmp("Device", tag) == 0) + { + // This closing tag shouldn't clear the accumulated text. + clearbuffer = false; + } + else if (strcmp("CaptureDevice", tag) == 0) + { + gVoiceClient->addCaptureDevice(textBuffer); + } + else if (strcmp("RenderDevice", tag) == 0) + { + gVoiceClient->addRenderDevice(textBuffer); + } + + if(clearbuffer) + { + textBuffer.clear(); + accumulateText= false; + } + + if (responseDepth == 0) + { + // We finished all of the XML, process the data + processResponse(tag); + } + } +} + +// -------------------------------------------------------------------------------- + +void LLVivoxProtocolParser::CharData(const char *buffer, int length) +{ + /* + This method is called for anything that isn't a tag, which can be text you + want that lies between tags, and a lot of stuff you don't want like file formatting + (tabs, spaces, CR/LF, etc). + + Only copy text if we are in accumulate mode... + */ + if (accumulateText) + textBuffer.append(buffer, length); +} + +// -------------------------------------------------------------------------------- + +void LLVivoxProtocolParser::processResponse(std::string tag) +{ +// llinfos << tag << llendl; + + if (isEvent) + { + if (eventTypeString == "LoginStateChangeEvent") + { + gVoiceClient->loginStateChangeEvent(accountHandle, statusCode, statusString, state); + } + else if (eventTypeString == "SessionNewEvent") + { + gVoiceClient->sessionNewEvent(accountHandle, eventSessionHandle, state, nameString, uriString); + } + else if (eventTypeString == "SessionStateChangeEvent") + { + gVoiceClient->sessionStateChangeEvent(uriString, statusCode, statusString, eventSessionHandle, state, isChannel, nameString); + } + else if (eventTypeString == "ParticipantStateChangeEvent") + { + gVoiceClient->participantStateChangeEvent(uriString, statusCode, statusString, state, nameString, displayNameString, participantType); + + } + else if (eventTypeString == "ParticipantPropertiesEvent") + { + gVoiceClient->participantPropertiesEvent(uriString, statusCode, statusString, isLocallyMuted, isModeratorMuted, isSpeaking, volume, energy); + } + else if (eventTypeString == "AuxAudioPropertiesEvent") + { + gVoiceClient->auxAudioPropertiesEvent(energy); + } + } + else + { + if (actionString == "Connector.Create.1") + { + gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle); + } + else if (actionString == "Account.Login.1") + { + gVoiceClient->loginResponse(statusCode, statusString, accountHandle); + } + else if (actionString == "Session.Create.1") + { + gVoiceClient->sessionCreateResponse(statusCode, statusString, sessionHandle); + } + else if (actionString == "Session.Connect.1") + { + gVoiceClient->sessionConnectResponse(statusCode, statusString); + } + else if (actionString == "Session.Terminate.1") + { + gVoiceClient->sessionTerminateResponse(statusCode, statusString); + } + else if (actionString == "Account.Logout.1") + { + gVoiceClient->logoutResponse(statusCode, statusString); + } + else if (actionString == "Connector.InitiateShutdown.1") + { + gVoiceClient->connectorShutdownResponse(statusCode, statusString); + } + else if (actionString == "Account.ChannelGetList.1") + { + gVoiceClient->channelGetListResponse(statusCode, statusString); + } +/* + else if (actionString == "Connector.AccountCreate.1") + { + + } + else if (actionString == "Connector.MuteLocalMic.1") + { + + } + else if (actionString == "Connector.MuteLocalSpeaker.1") + { + + } + else if (actionString == "Connector.SetLocalMicVolume.1") + { + + } + else if (actionString == "Connector.SetLocalSpeakerVolume.1") + { + + } + else if (actionString == "Session.ListenerSetPosition.1") + { + + } + else if (actionString == "Session.SpeakerSetPosition.1") + { + + } + else if (actionString == "Session.Set3DPosition.1") + { + + } + else if (actionString == "Session.AudioSourceSetPosition.1") + { + + } + else if (actionString == "Session.GetChannelParticipants.1") + { + + } + else if (actionString == "Account.ChannelCreate.1") + { + + } + else if (actionString == "Account.ChannelUpdate.1") + { + + } + else if (actionString == "Account.ChannelDelete.1") + { + + } + else if (actionString == "Account.ChannelCreateAndInvite.1") + { + + } + else if (actionString == "Account.ChannelFolderCreate.1") + { + + } + else if (actionString == "Account.ChannelFolderUpdate.1") + { + + } + else if (actionString == "Account.ChannelFolderDelete.1") + { + + } + else if (actionString == "Account.ChannelAddModerator.1") + { + + } + else if (actionString == "Account.ChannelDeleteModerator.1") + { + + } +*/ + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + +class LLVoiceClientPrefsListener: public LLSimpleListener +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + // Note: Ignore the specific event value, look up the ones we want + + gVoiceClient->setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat")); + gVoiceClient->setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled")); + std::string keyString = gSavedSettings.getString("PushToTalkButton"); + gVoiceClient->setPTTKey(keyString); + gVoiceClient->setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle")); + gVoiceClient->setEarLocation(gSavedSettings.getS32("VoiceEarLocation")); + std::string serverName = gSavedSettings.getString("VivoxDebugServerName"); + gVoiceClient->setVivoxDebugServerName(serverName); + + std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice"); + gVoiceClient->setCaptureDevice(inputDevice); + std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice"); + gVoiceClient->setRenderDevice(outputDevice); + + return true; + } +}; +static LLVoiceClientPrefsListener voice_prefs_listener; + +class LLVoiceClientMuteListObserver : public LLMuteListObserver +{ + /* virtual */ void onChange() { gVoiceClient->muteListChanged();} +}; +static LLVoiceClientMuteListObserver mutelist_listener; +static bool sMuteListListener_listening = false; + +/////////////////////////////////////////////////////////////////////////////////////////////// + +class LLVoiceClientCapResponder : public LLHTTPClient::Responder +{ +public: + LLVoiceClientCapResponder(void){}; + + virtual void error(U32 status, const std::string& reason); // called with bad status codes + virtual void result(const LLSD& content); + +private: +}; + +void LLVoiceClientCapResponder::error(U32 status, const std::string& reason) +{ + llwarns << "LLVoiceClientCapResponder::error(" + << status << ": " << reason << ")" + << llendl; +} + +void LLVoiceClientCapResponder::result(const LLSD& content) +{ + LLSD::map_const_iterator iter; + for(iter = content.beginMap(); iter != content.endMap(); ++iter) + { + llinfos << "LLVoiceClientCapResponder::result got " + << iter->first << llendl; + } + + if ( content.has("voice_credentials") ) + { + LLSD voice_credentials = content["voice_credentials"]; + std::string uri; + std::string credentials; + + if ( voice_credentials.has("channel_uri") ) + { + uri = voice_credentials["channel_uri"].asString(); + } + if ( voice_credentials.has("channel_credentials") ) + { + credentials = + voice_credentials["channel_credentials"].asString(); + } + + gVoiceClient->setSpatialChannel(uri, credentials); + } +} + + + +#if LL_WINDOWS +static HANDLE sGatewayHandle = 0; + +static bool isGatewayRunning() +{ + bool result = false; + if(sGatewayHandle != 0) + { + DWORD waitresult = WaitForSingleObject(sGatewayHandle, 0); + if(waitresult != WAIT_OBJECT_0) + { + result = true; + } + } + return result; +} +static void killGateway() +{ + if(sGatewayHandle != 0) + { + TerminateProcess(sGatewayHandle,0); + } +} + +#else // Mac and linux + +static pid_t sGatewayPID = 0; +static bool isGatewayRunning() +{ + bool result = false; + if(sGatewayPID != 0) + { + // A kill with signal number 0 has no effect, just does error checking. It should return an error if the process no longer exists. + if(kill(sGatewayPID, 0) == 0) + { + result = true; + } + } + return result; +} + +static void killGateway() +{ + if(sGatewayPID != 0) + { + kill(sGatewayPID, SIGTERM); + } +} + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////// + +LLVoiceClient::LLVoiceClient() +{ + gVoiceClient = this; + mWriteInProgress = false; + mAreaVoiceDisabled = false; + mPTT = true; + mUserPTTState = false; + mMuteMic = false; + mSessionTerminateRequested = false; + mCommandCookie = 0; + mNonSpatialChannel = false; + mNextSessionSpatial = true; + mNextSessionNoReconnect = false; + mSessionP2P = false; + mCurrentParcelLocalID = 0; + mLoginRetryCount = 0; + mVivoxErrorStatusCode = 0; + + mNextSessionResetOnClose = false; + mSessionResetOnClose = false; + mSpeakerVolume = 0; + mMicVolume = 0; + + // Initial dirty state + mSpatialCoordsDirty = false; + mPTTDirty = true; + mVolumeDirty = true; + mSpeakerVolumeDirty = true; + mMicVolumeDirty = true; + mCaptureDeviceDirty = false; + mRenderDeviceDirty = false; + + // Load initial state from prefs. + mVoiceEnabled = gSavedSettings.getBOOL("EnableVoiceChat"); + mUsePTT = gSavedSettings.getBOOL("EnablePushToTalk"); + std::string keyString = gSavedSettings.getString("PushToTalkButton"); + setPTTKey(keyString); + mPTTIsToggle = gSavedSettings.getBOOL("PushToTalkToggle"); + mEarLocation = gSavedSettings.getS32("VoiceEarLocation"); + setVoiceVolume(gSavedSettings.getF32("AudioLevelVoice")); + std::string captureDevice = gSavedSettings.getString("VoiceInputAudioDevice"); + setCaptureDevice(captureDevice); + std::string renderDevice = gSavedSettings.getString("VoiceOutputAudioDevice"); + setRenderDevice(renderDevice); + + // Set up our listener to get updates on all prefs values we care about. + gSavedSettings.getControl("EnableVoiceChat")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("PTTCurrentlyEnabled")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("PushToTalkButton")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("PushToTalkToggle")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("VoiceEarLocation")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("VivoxDebugServerName")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("VoiceInputAudioDevice")->addListener(&voice_prefs_listener); + gSavedSettings.getControl("VoiceOutputAudioDevice")->addListener(&voice_prefs_listener); + + mTuningMode = false; + mTuningEnergy = 0.0f; + mTuningMicVolume = 0; + mTuningMicVolumeDirty = true; + mTuningSpeakerVolume = 0; + mTuningSpeakerVolumeDirty = true; + mTuningCaptureRunning = false; + + // gMuteListp isn't set up at this point, so we defer this until later. +// gMuteListp->addObserver(&mutelist_listener); + + mParticipantMapChanged = false; + + // stash the pump for later use + // This now happens when init() is called instead. + mPump = NULL; + +#if LL_DARWIN || LL_LINUX + // MBW -- XXX -- THIS DOES NOT BELONG HERE + // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us. + // This should cause us to ignore SIGPIPE and handle the error through proper channels. + // This should really be set up elsewhere. Where should it go? + signal(SIGPIPE, SIG_IGN); + + // Since we're now launching the gateway with fork/exec instead of system(), we need to deal with zombie processes. + // Ignoring SIGCHLD should prevent zombies from being created. Alternately, we could use wait(), but I'd rather not do that. + signal(SIGCHLD, SIG_IGN); +#endif + + // set up state machine + setState(stateDisabled); + + gIdleCallbacks.addFunction(idle, this); +} + +//--------------------------------------------------- + +LLVoiceClient::~LLVoiceClient() +{ +} + +//---------------------------------------------- + + + +void LLVoiceClient::init(LLPumpIO *pump) +{ + // constructor will set up gVoiceClient + LLVoiceClient::getInstance()->mPump = pump; +} + +void LLVoiceClient::terminate() +{ + if(gVoiceClient) + { + gVoiceClient->sessionTerminateSendMessage(); + gVoiceClient->logout(); + gVoiceClient->connectorShutdown(); + gVoiceClient->closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. + + // This will do unpleasant things on windows. +// killGateway(); + + // Don't do this anymore -- LLSingleton will take care of deleting the object. +// delete gVoiceClient; + + // Hint to other code not to access the voice client anymore. + gVoiceClient = NULL; + } +} + + +///////////////////////////// +// utility functions + +bool LLVoiceClient::writeString(const std::string &str) +{ + bool result = false; + if(mConnected) + { + apr_status_t err; + apr_size_t size = (apr_size_t)str.size(); + apr_size_t written = size; + +// llinfos << "sending: " << str << llendl; + + // MBW -- XXX -- check return code - sockets will fail (broken, etc.) + err = apr_socket_send( + mSocket->getSocket(), + (const char*)str.data(), + &written); + + if(err == 0) + { + // Success. + result = true; + } + // MBW -- XXX -- handle partial writes (written is number of bytes written) + // Need to set socket to non-blocking before this will work. +// else if(APR_STATUS_IS_EAGAIN(err)) +// { +// // +// } + else + { + // Assume any socket error means something bad. For now, just close the socket. + char buf[MAX_STRING]; + llwarns << "apr error " << err << " ("<< apr_strerror(err, buf, MAX_STRING) << ") sending data to vivox daemon." << llendl; + daemonDied(); + } + } + + return result; +} + + +///////////////////////////// +// session control messages +void LLVoiceClient::connectorCreate() +{ + std::ostringstream stream; + std::string logpath; + std::string loglevel = "0"; + + // Transition to stateConnectorStarted when the connector handle comes back. + setState(stateConnectorStarting); + + std::string savedLogLevel = gSavedSettings.getString("VivoxDebugLevel"); + + if(savedLogLevel != "-1") + { + llinfos << "creating connector with logging enabled" << llendl; + loglevel = "10"; + logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + } + + stream + << "" + << "V2 SDK" + << "" << mAccountServerURI << "" + << "" + << "false" + << "" << logpath << "" + << "Connector" + << ".log" + << "" << loglevel << "" + << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::connectorShutdown() +{ + setState(stateConnectorStopping); + + if(!mConnectorHandle.empty()) + { + std::ostringstream stream; + stream + << "" + << "" << mConnectorHandle << "" + << "" + << "\n\n\n"; + + mConnectorHandle.clear(); + + writeString(stream.str()); + } +} + +void LLVoiceClient::userAuthorized(const std::string& firstName, const std::string& lastName, const LLUUID &agentID) +{ + mAccountFirstName = firstName; + mAccountLastName = lastName; + + mAccountDisplayName = firstName; + mAccountDisplayName += " "; + mAccountDisplayName += lastName; + + llinfos << "name \"" << mAccountDisplayName << "\" , ID " << agentID << llendl; + + std::string userserver = gUserServerName; + LLString::toLower(userserver); + if((gUserServerChoice == USERSERVER_AGNI) || + ((gUserServerChoice == USERSERVER_OTHER) && (userserver.find("agni") != std::string::npos))) + { + sConnectingToAgni = true; + } + + // MBW -- XXX -- Enable this when the bhd.vivox.com server gets a real ssl cert. + if(sConnectingToAgni) + { + // Use the release account server + mAccountServerName = "bhr.vivox.com"; + mAccountServerURI = "https://www." + mAccountServerName + "/api2/"; + } + else + { + // Use the development account server + mAccountServerName = gSavedSettings.getString("VivoxDebugServerName"); + mAccountServerURI = "https://www." + mAccountServerName + "/api2/"; + } + + mAccountName = nameFromID(agentID); +} + +void LLVoiceClient::requestVoiceAccountProvision(S32 retries) +{ + if ( gAgent.getRegion() && mVoiceEnabled ) + { + std::string url = + gAgent.getRegion()->getCapability( + "ProvisionVoiceAccountRequest"); + + if ( url == "" ) return; + + LLHTTPClient::post( + url, + LLSD(), + new LLViewerVoiceAccountProvisionResponder(retries)); + } +} + +void LLVoiceClient::login( + const std::string& accountName, + const std::string &password) +{ + if((getState() >= stateLoggingIn) && (getState() < stateLoggedOut)) + { + // Already logged in. This is an internal error. + llerrs << "called from wrong state." << llendl; + } + else if ( accountName != mAccountName ) + { + //TODO: error? + llinfos << "Wrong account name! " << accountName + << " instead of " << mAccountName << llendl; + } + else + { + mAccountPassword = password; + } +} + +void LLVoiceClient::idle(void* user_data) +{ + LLVoiceClient* self = (LLVoiceClient*)user_data; + self->stateMachine(); +} + +const char *LLVoiceClient::state2string(LLVoiceClient::state inState) +{ + const char *result = "UNKNOWN"; + + // Prevent copy-paste errors when updating this list... +#define CASE(x) case x: result = #x; break + + switch(inState) + { + CASE(stateDisabled); + CASE(stateStart); + CASE(stateDaemonLaunched); + CASE(stateConnecting); + CASE(stateIdle); + CASE(stateConnectorStart); + CASE(stateConnectorStarting); + CASE(stateConnectorStarted); + CASE(stateMicTuningNoLogin); + CASE(stateLoginRetry); + CASE(stateLoginRetryWait); + CASE(stateNeedsLogin); + CASE(stateLoggingIn); + CASE(stateLoggedIn); + CASE(stateNoChannel); + CASE(stateMicTuningLoggedIn); + CASE(stateSessionCreate); + CASE(stateSessionConnect); + CASE(stateJoiningSession); + CASE(stateSessionJoined); + CASE(stateRunning); + CASE(stateLeavingSession); + CASE(stateSessionTerminated); + CASE(stateLoggingOut); + CASE(stateLoggedOut); + CASE(stateConnectorStopping); + CASE(stateConnectorStopped); + CASE(stateConnectorFailed); + CASE(stateConnectorFailedWaiting); + CASE(stateLoginFailed); + CASE(stateLoginFailedWaiting); + CASE(stateJoinSessionFailed); + CASE(stateJoinSessionFailedWaiting); + CASE(stateJail); + } + +#undef CASE + + return result; +} + +const char *LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserver::EStatusType inStatus) +{ + const char *result = "UNKNOWN"; + + // Prevent copy-paste errors when updating this list... +#define CASE(x) case x: result = #x; break + + switch(inStatus) + { + CASE(STATUS_JOINING); + CASE(STATUS_JOINED); + CASE(STATUS_LEFT_CHANNEL); + CASE(ERROR_CHANNEL_FULL); + CASE(ERROR_CHANNEL_LOCKED); + CASE(ERROR_UNKNOWN); + default: + break; + } + +#undef CASE + + return result; +} + +void LLVoiceClient::setState(state inState) +{ + llinfos << "entering state " << state2string(inState) << llendl; + + mState = inState; +} + +void LLVoiceClient::stateMachine() +{ + if(gDisconnected) + { + // The viewer has been disconnected from the sim. Disable voice. + setVoiceEnabled(false); + } + + if(!mVoiceEnabled) + { + if(getState() != stateDisabled) + { + // User turned off voice support. Send the cleanup messages, close the socket, and reset. + if(!mConnected) + { + // if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill. + llinfos << "Disabling voice before connection to daemon, terminating." << llendl; + killGateway(); + } + + sessionTerminateSendMessage(); + logout(); + connectorShutdown(); + closeSocket(); + removeAllParticipants(); + + setState(stateDisabled); + } + } + + // Check for parcel boundary crossing + { + LLViewerRegion *region = gAgent.getRegion(); + LLParcel *parcel = NULL; + + if(gParcelMgr) + { + parcel = gParcelMgr->getAgentParcel(); + } + + if(region && parcel) + { + S32 parcelLocalID = parcel->getLocalID(); + std::string regionName = region->getName(); + std::string capURI = region->getCapability("ParcelVoiceInfoRequest"); + +// llinfos << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << llendl; + + // The region name starts out empty and gets filled in later. + // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes. + // If either is empty, wait for the next time around. + if(!regionName.empty() && !capURI.empty()) + { + if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) + { + // We have changed parcels. Initiate a parcel channel lookup. + mCurrentParcelLocalID = parcelLocalID; + mCurrentRegionName = regionName; + + parcelChanged(); + } + } + } + } + + switch(getState()) + { + case stateDisabled: + if(mVoiceEnabled && (!mAccountName.empty() || mTuningMode)) + { + setState(stateStart); + } + break; + + case stateStart: + if(gDisableVoice) + { + // Voice is locked out, we must not launch the vivox daemon. + setState(stateJail); + } + else if(!isGatewayRunning()) + { + if(true) + { + // Launch the voice daemon + std::string exe_path = gDirUtilp->getAppRODataDir(); + exe_path += gDirUtilp->getDirDelimiter(); +#if LL_WINDOWS + exe_path += "SLVoice.exe"; +#else + // This will be the same for mac and linux + exe_path += "SLVoice"; +#endif + // See if the vivox executable exists + llstat s; + if(!LLFile::stat(exe_path.c_str(), &s)) + { + // vivox executable exists. Build the command line and launch the daemon. + std::string args = " -p tcp -h -c"; + std::string cmd; + std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); + + if(loglevel.empty()) + { + loglevel = "-1"; // turn logging off completely + } + + args += " -ll "; + args += loglevel; + +// llinfos << "Args for SLVoice: " << args << llendl; + +#if LL_WINDOWS + PROCESS_INFORMATION pinfo; + STARTUPINFOA sinfo; + memset(&sinfo, 0, sizeof(sinfo)); + std::string exe_dir = gDirUtilp->getAppRODataDir(); + cmd = "SLVoice.exe"; + cmd += args; + + // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... + char *args2 = new char[args.size() + 1]; + strcpy(args2, args.c_str()); + + if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) + { +// DWORD dwErr = GetLastError(); + } + else + { + // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on + // CloseHandle(pinfo.hProcess); // stops leaks - nothing else + sGatewayHandle = pinfo.hProcess; + CloseHandle(pinfo.hThread); // stops leaks - nothing else + } + + delete args2; +#else // LL_WINDOWS + // This should be the same for mac and linux + { + std::vector arglist; + arglist.push_back(exe_path.c_str()); + + // Split the argument string into separate strings for each argument + typedef boost::tokenizer > tokenizer; + boost::char_separator sep(" "); + tokenizer tokens(args, sep); + tokenizer::iterator token_iter; + + for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) + { + arglist.push_back(*token_iter); + } + + // create an argv vector for the child process + char **fakeargv = new char*[arglist.size() + 1]; + int i; + for(i=0; i < arglist.size(); i++) + fakeargv[i] = const_cast(arglist[i].c_str()); + + fakeargv[i] = NULL; + + pid_t id = vfork(); + if(id == 0) + { + // child + execv(exe_path.c_str(), fakeargv); + + // If we reach this point, the exec failed. + // Use _exit() instead of exit() per the vfork man page. + _exit(0); + } + + // parent + delete[] fakeargv; + sGatewayPID = id; + } +#endif // LL_WINDOWS + mDaemonHost = LLHost("127.0.0.1", 44124); + } + else + { + llinfos << exe_path << "not found." << llendl + } + } + else + { + // We can connect to a client gateway running on another host. This is useful for testing. + // To do this, launch the gateway on a nearby host like this: + // vivox-gw.exe -p tcp -i 0.0.0.0:44124 + // and put that host's IP address here. + mDaemonHost = LLHost("127.0.0.1", 44124); + } + + mUpdateTimer.start(); + mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); + + setState(stateDaemonLaunched); + + // Dirty the states we'll need to sync with the daemon when it comes up. + mPTTDirty = true; + mSpeakerVolumeDirty = true; + // These only need to be set if they're not default (i.e. empty string). + mCaptureDeviceDirty = !mCaptureDevice.empty(); + mRenderDeviceDirty = !mRenderDevice.empty(); + } + break; + + case stateDaemonLaunched: +// llinfos << "Connecting to vivox daemon" << llendl; + if(mUpdateTimer.hasExpired()) + { + mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); + + if(!mSocket) + { + mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + } + + mConnected = mSocket->blockingConnect(mDaemonHost); + if(mConnected) + { + setState(stateConnecting); + } + else + { + // If the connect failed, the socket may have been put into a bad state. Delete it. + closeSocket(); + } + } + break; + + case stateConnecting: + // Can't do this until we have the pump available. + if(mPump) + { + // MBW -- Note to self: pumps and pipes examples in + // indra/test/io.cpp + // indra/test/llpipeutil.{cpp|h} + + // Attach the pumps and pipes + + LLPumpIO::chain_t readChain; + + readChain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(mSocket))); + readChain.push_back(LLIOPipe::ptr_t(new LLVivoxProtocolParser())); + + mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS); + + setState(stateIdle); + } + + break; + + case stateIdle: + // Initial devices query + getCaptureDevicesSendMessage(); + getRenderDevicesSendMessage(); + + mLoginRetryCount = 0; + + setState(stateConnectorStart); + + break; + + case stateConnectorStart: + if(!mVoiceEnabled) + { + // We were never logged in. This will shut down the connector. + setState(stateLoggedOut); + } + else if(!mAccountServerURI.empty()) + { + connectorCreate(); + } + else if(mTuningMode) + { + setState(stateMicTuningNoLogin); + } + break; + + case stateConnectorStarting: // waiting for connector handle + // connectorCreateResponse() will transition from here to stateConnectorStarted. + break; + + case stateConnectorStarted: // connector handle received + if(!mVoiceEnabled) + { + // We were never logged in. This will shut down the connector. + setState(stateLoggedOut); + } + else if(!mAccountName.empty()) + { + LLViewerRegion *region = gAgent.getRegion(); + + if(region) + { + if ( region->getCapability("ProvisionVoiceAccountRequest") != "" ) + { + if ( mAccountPassword.empty() ) + { + requestVoiceAccountProvision(); + } + setState(stateNeedsLogin); + } + } + } + break; + + case stateMicTuningNoLogin: + case stateMicTuningLoggedIn: + { + // Both of these behave essentially the same. The only difference is where the exit transition goes to. + if(mTuningMode && mVoiceEnabled && !mSessionTerminateRequested) + { + if(!mTuningCaptureRunning) + { + // duration parameter is currently unused, per Mike S. + tuningCaptureStartSendMessage(10000); + } + + if(mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty || mCaptureDeviceDirty || mRenderDeviceDirty) + { + std::ostringstream stream; + + if(mTuningMicVolumeDirty) + { + stream + << "" + << "" << mTuningMicVolume << "" + << "\n\n\n"; + } + + if(mTuningSpeakerVolumeDirty) + { + stream + << "" + << "" << mTuningSpeakerVolume << "" + << "\n\n\n"; + } + + if(mCaptureDeviceDirty) + { + buildSetCaptureDevice(stream); + } + + if(mRenderDeviceDirty) + { + buildSetRenderDevice(stream); + } + + mTuningMicVolumeDirty = false; + mTuningSpeakerVolumeDirty = false; + mCaptureDeviceDirty = false; + mRenderDeviceDirty = false; + + if(!stream.str().empty()) + { + writeString(stream.str()); + } + } + } + else + { + // transition out of mic tuning + if(mTuningCaptureRunning) + { + tuningCaptureStopSendMessage(); + } + + if(getState() == stateMicTuningNoLogin) + { + setState(stateConnectorStart); + } + else + { + setState(stateNoChannel); + } + } + } + break; + + case stateLoginRetry: + if(mLoginRetryCount == 0) + { + // First retry -- display a message to the user + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGIN_RETRY); + } + + mLoginRetryCount++; + + if(mLoginRetryCount > MAX_LOGIN_RETRIES) + { + llinfos << "too many login retries, giving up." << llendl; + setState(stateLoginFailed); + } + else + { + llinfos << "will retry login in " << LOGIN_RETRY_SECONDS << " seconds." << llendl; + mUpdateTimer.start(); + mUpdateTimer.setTimerExpirySec(LOGIN_RETRY_SECONDS); + setState(stateLoginRetryWait); + } + break; + + case stateLoginRetryWait: + if(mUpdateTimer.hasExpired()) + { + setState(stateNeedsLogin); + } + break; + + case stateNeedsLogin: + if(!mAccountPassword.empty()) + { + setState(stateLoggingIn); + loginSendMessage(); + } + break; + + case stateLoggingIn: // waiting for account handle + // loginResponse() will transition from here to stateLoggedIn. + break; + + case stateLoggedIn: // account handle received + // Initial kick-off of channel lookup logic + parcelChanged(); + + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN); + + // Set up the mute list observer if it hasn't been set up already. + if((!sMuteListListener_listening) && (gMuteListp)) + { + gMuteListp->addObserver(&mutelist_listener); + sMuteListListener_listening = true; + } + + setState(stateNoChannel); + break; + + case stateNoChannel: + if(mSessionTerminateRequested || !mVoiceEnabled) + { + // MBW -- XXX -- Is this the right way out of this state? + setState(stateSessionTerminated); + } + else if(mTuningMode) + { + setState(stateMicTuningLoggedIn); + } + else if(!mNextSessionHandle.empty()) + { + setState(stateSessionConnect); + } + else if(!mNextSessionURI.empty()) + { + setState(stateSessionCreate); + } + break; + + case stateSessionCreate: + sessionCreateSendMessage(); + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING); + setState(stateJoiningSession); + break; + + case stateSessionConnect: + sessionConnectSendMessage(); + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING); + setState(stateJoiningSession); + break; + + case stateJoiningSession: // waiting for session handle + // sessionCreateResponse() will transition from here to stateSessionJoined. + if(!mVoiceEnabled) + { + // User bailed out during connect -- jump straight to teardown. + setState(stateSessionTerminated); + } + else if(mSessionTerminateRequested) + { + if(!mSessionHandle.empty()) + { + // Only allow direct exits from this state in p2p calls (for cancelling an invite). + // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway. + if(mSessionP2P) + { + sessionTerminateSendMessage(); + setState(stateSessionTerminated); + } + } + } + break; + + case stateSessionJoined: // session handle received + // MBW -- XXX -- It appears that I need to wait for BOTH the Session.Create response and the SessionStateChangeEvent with state 4 + // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck. + // For now, the Session.Create response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined. + // This is a cheap way to make sure both have happened before proceeding. + if(!mSessionHandle.empty()) + { + // Events that need to happen when a session is joined could go here. + // Maybe send initial spatial data? + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED); + + // Dirty state that may need to be sync'ed with the daemon. + mPTTDirty = true; + mSpeakerVolumeDirty = true; + mSpatialCoordsDirty = true; + + setState(stateRunning); + + // Start the throttle timer + mUpdateTimer.start(); + mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS); + } + else if(!mVoiceEnabled) + { + // User bailed out during connect -- jump straight to teardown. + setState(stateSessionTerminated); + } + else if(mSessionTerminateRequested) + { + // Only allow direct exits from this state in p2p calls (for cancelling an invite). + // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway. + if(mSessionP2P) + { + sessionTerminateSendMessage(); + setState(stateSessionTerminated); + } + } + break; + + case stateRunning: // steady state + // sessionTerminateSendMessage() will transition from here to stateLeavingSession + + // Disabling voice or disconnect requested. + if(!mVoiceEnabled || mSessionTerminateRequested) + { + sessionTerminateSendMessage(); + } + else + { + + // Figure out whether the PTT state needs to change + { + bool newPTT; + if(mUsePTT) + { + // If configured to use PTT, track the user state. + newPTT = mUserPTTState; + } + else + { + // If not configured to use PTT, it should always be true (otherwise the user will be unable to speak). + newPTT = true; + } + + if(mMuteMic) + { + // This always overrides any other PTT setting. + newPTT = false; + } + + // Dirty if state changed. + if(newPTT != mPTT) + { + mPTT = newPTT; + mPTTDirty = true; + } + } + + if(mNonSpatialChannel) + { + // When in a non-spatial channel, never send positional updates. + mSpatialCoordsDirty = false; + } + else + { + // Do the calculation that enforces the listener<->speaker tether (and also updates the real camera position) + enforceTether(); + } + + // Send an update if the ptt state has changed (which shouldn't be able to happen that often -- the user can only click so fast) + // or every 10hz, whichever is sooner. + if(mVolumeDirty || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired()) + { + mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS); + sendPositionalUpdate(); + } + } + break; + + case stateLeavingSession: // waiting for terminate session response + // The handler for the Session.Terminate response will transition from here to stateSessionTerminated. + break; + + case stateSessionTerminated: + // Always reset the terminate request flag when we get here. + mSessionTerminateRequested = false; + + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); + + if(mVoiceEnabled) + { + // SPECIAL CASE: if going back to spatial but in a parcel with an empty URI, transfer the non-spatial flag now. + // This fixes the case where you come out of a group chat in a parcel with voice disabled, and get stuck unable to rejoin spatial chat thereafter. + if(mNextSessionSpatial && mNextSessionURI.empty()) + { + mNonSpatialChannel = !mNextSessionSpatial; + } + + // Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state). + setState(stateNoChannel); + } + else + { + // Shutting down voice, continue with disconnecting. + logout(); + } + + break; + + case stateLoggingOut: // waiting for logout response + // The handler for the Account.Logout response will transition from here to stateLoggedOut. + break; + case stateLoggedOut: // logout response received + // shut down the connector + connectorShutdown(); + break; + + case stateConnectorStopping: // waiting for connector stop + // The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped. + break; + + case stateConnectorStopped: // connector stop received + // Clean up and reset everything. + closeSocket(); + removeAllParticipants(); + setState(stateDisabled); + break; + + case stateConnectorFailed: + setState(stateConnectorFailedWaiting); + break; + case stateConnectorFailedWaiting: + break; + + case stateLoginFailed: + setState(stateLoginFailedWaiting); + break; + case stateLoginFailedWaiting: + // No way to recover from these. Yet. + break; + + case stateJoinSessionFailed: + // Transition to error state. Send out any notifications here. + llwarns << "stateJoinSessionFailed: (" << mVivoxErrorStatusCode << "): " << mVivoxErrorStatusString << llendl; + notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN); + setState(stateJoinSessionFailedWaiting); + break; + + case stateJoinSessionFailedWaiting: + // Joining a channel failed, either due to a failed channel name -> sip url lookup or an error from the join message. + // Region crossings may leave this state and try the join again. + if(mSessionTerminateRequested) + { + setState(stateSessionTerminated); + } + break; + + case stateJail: + // We have given up. Do nothing. + break; + } + + if(mParticipantMapChanged) + { + mParticipantMapChanged = false; + notifyObservers(); + } + +} + +void LLVoiceClient::closeSocket(void) +{ + mSocket.reset(); + mConnected = false; +} + +void LLVoiceClient::loginSendMessage() +{ + std::ostringstream stream; + stream + << "" + << "" << mConnectorHandle << "" + << "" << mAccountName << "" + << "" << mAccountPassword << "" + << "VerifyAnswer" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::logout() +{ + mAccountPassword = ""; + setState(stateLoggingOut); + logoutSendMessage(); +} + +void LLVoiceClient::logoutSendMessage() +{ + if(!mAccountHandle.empty()) + { + std::ostringstream stream; + stream + << "" + << "" << mAccountHandle << "" + << "" + << "\n\n\n"; + + mAccountHandle.clear(); + + writeString(stream.str()); + } +} + +void LLVoiceClient::channelGetListSendMessage() +{ + std::ostringstream stream; + stream + << "" + << "" << mAccountHandle << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::sessionCreateSendMessage() +{ + llinfos << "requesting join: " << mNextSessionURI << llendl; + + mSessionURI = mNextSessionURI; + mNonSpatialChannel = !mNextSessionSpatial; + mSessionResetOnClose = mNextSessionResetOnClose; + mNextSessionResetOnClose = false; + if(mNextSessionNoReconnect) + { + // Clear the stashed URI so it can't reconnect + mNextSessionURI.clear(); + } + // Only p2p sessions are created with "no reconnect". + mSessionP2P = mNextSessionNoReconnect; + + std::ostringstream stream; + stream + << "" + << "" << mAccountHandle << "" + << "" << mSessionURI << ""; + + static const std::string allowed_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789" + "-._~"; + + if(!mNextSessionHash.empty()) + { + stream + << "" << LLURI::escape(mNextSessionHash, allowed_chars) << "" + << "SHA1UserName"; + } + + stream + << "" << mChannelName << "" + << "\n\n\n"; + writeString(stream.str()); +} + +void LLVoiceClient::sessionConnectSendMessage() +{ + llinfos << "connecting to session handle: " << mNextSessionHandle << llendl; + + mSessionHandle = mNextSessionHandle; + mSessionURI = mNextP2PSessionURI; + mNextSessionHandle.clear(); // never want to re-use these. + mNextP2PSessionURI.clear(); + mNonSpatialChannel = !mNextSessionSpatial; + mSessionResetOnClose = mNextSessionResetOnClose; + mNextSessionResetOnClose = false; + // Joining by session ID is only used to answer p2p invitations, so we know this is a p2p session. + mSessionP2P = true; + + std::ostringstream stream; + + stream + << "" + << "" << mSessionHandle << "" + << "default" + << "\n\n\n"; + writeString(stream.str()); +} + +void LLVoiceClient::sessionTerminate() +{ + mSessionTerminateRequested = true; +} + +void LLVoiceClient::sessionTerminateSendMessage() +{ + llinfos << "leaving session: " << mSessionURI << llendl; + + switch(getState()) + { + case stateNoChannel: + // In this case, we want to pretend the join failed so our state machine doesn't get stuck. + // Skip the join failed transition state so we don't send out error notifications. + setState(stateJoinSessionFailedWaiting); + break; + case stateJoiningSession: + case stateSessionJoined: + case stateRunning: + if(!mSessionHandle.empty()) + { + sessionTerminateByHandle(mSessionHandle); + setState(stateLeavingSession); + } + else + { + llwarns << "called with no session handle" << llendl; + setState(stateSessionTerminated); + } + break; + case stateJoinSessionFailed: + case stateJoinSessionFailedWaiting: + setState(stateSessionTerminated); + break; + + default: + llwarns << "called from unknown state" << llendl; + break; + } +} + +void LLVoiceClient::sessionTerminateByHandle(std::string &sessionHandle) +{ + llinfos << "Sending Session.Terminate with handle " << sessionHandle << llendl; + + std::ostringstream stream; + stream + << "" + << "" << sessionHandle << "" + << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::getCaptureDevicesSendMessage() +{ + std::ostringstream stream; + stream + << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::getRenderDevicesSendMessage() +{ + std::ostringstream stream; + stream + << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::clearCaptureDevices() +{ + // MBW -- XXX -- do something here + llinfos << "called" << llendl; + mCaptureDevices.clear(); +} + +void LLVoiceClient::addCaptureDevice(const std::string& name) +{ + // MBW -- XXX -- do something here + llinfos << name << llendl; + + mCaptureDevices.push_back(name); +} + +LLVoiceClient::deviceList *LLVoiceClient::getCaptureDevices() +{ + return &mCaptureDevices; +} + +void LLVoiceClient::setCaptureDevice(const std::string& name) +{ + if(name == "Default") + { + if(!mCaptureDevice.empty()) + { + mCaptureDevice.clear(); + mCaptureDeviceDirty = true; + } + } + else + { + if(mCaptureDevice != name) + { + mCaptureDevice = name; + mCaptureDeviceDirty = true; + } + } +} + +void LLVoiceClient::clearRenderDevices() +{ + // MBW -- XXX -- do something here + llinfos << "called" << llendl; + mRenderDevices.clear(); +} + +void LLVoiceClient::addRenderDevice(const std::string& name) +{ + // MBW -- XXX -- do something here + llinfos << name << llendl; + mRenderDevices.push_back(name); +} + +LLVoiceClient::deviceList *LLVoiceClient::getRenderDevices() +{ + return &mRenderDevices; +} + +void LLVoiceClient::setRenderDevice(const std::string& name) +{ + if(name == "Default") + { + if(!mRenderDevice.empty()) + { + mRenderDevice.clear(); + mRenderDeviceDirty = true; + } + } + else + { + if(mRenderDevice != name) + { + mRenderDevice = name; + mRenderDeviceDirty = true; + } + } + +} + +void LLVoiceClient::tuningStart() +{ + mTuningMode = true; + if(getState() >= stateNoChannel) + { + sessionTerminate(); + } +} + +void LLVoiceClient::tuningStop() +{ + mTuningMode = false; +} + +bool LLVoiceClient::inTuningMode() +{ + bool result = false; + switch(getState()) + { + case stateMicTuningNoLogin: + case stateMicTuningLoggedIn: + result = true; + default: + break; + } + return result; +} + +void LLVoiceClient::tuningRenderStartSendMessage(const std::string& name, bool loop) +{ + if(!inTuningMode()) + return; + + mTuningAudioFile = name; + std::ostringstream stream; + stream + << "" + << "" << mTuningAudioFile << "" + << "" << (loop?"1":"0") << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::tuningRenderStopSendMessage() +{ + if(!inTuningMode()) + return; + + std::ostringstream stream; + stream + << "" + << "" << mTuningAudioFile << "" + << "\n\n\n"; + + writeString(stream.str()); +} + +void LLVoiceClient::tuningCaptureStartSendMessage(int duration) +{ + if(!inTuningMode()) + return; + + std::ostringstream stream; + stream + << "" + << "" << duration << "" + << "\n\n\n"; + + writeString(stream.str()); + + mTuningCaptureRunning = true; +} + +void LLVoiceClient::tuningCaptureStopSendMessage() +{ + if(!inTuningMode()) + return; + + std::ostringstream stream; + stream + << "" + << "\n\n\n"; + + writeString(stream.str()); + + mTuningCaptureRunning = false; +} + +void LLVoiceClient::tuningSetMicVolume(float volume) +{ + int scaledVolume = ((int)(volume * 100.0f)) - 100; + if(scaledVolume != mTuningMicVolume) + { + mTuningMicVolume = scaledVolume; + mTuningMicVolumeDirty = true; + } +} + +void LLVoiceClient::tuningSetSpeakerVolume(float volume) +{ + int scaledVolume = ((int)(volume * 100.0f)) - 100; + if(scaledVolume != mTuningSpeakerVolume) + { + mTuningSpeakerVolume = ((int)(volume * 100.0f)) - 100; + mTuningSpeakerVolumeDirty = true; + } +} + +float LLVoiceClient::tuningGetEnergy(void) +{ + return mTuningEnergy; +} + +bool LLVoiceClient::deviceSettingsAvailable() +{ + bool result = true; + + if(!mConnected) + result = false; + + if(mRenderDevices.empty()) + result = false; + + return result; +} + +void LLVoiceClient::refreshDeviceLists(bool clearCurrentList) +{ + if(clearCurrentList) + { + clearCaptureDevices(); + clearRenderDevices(); + } + getCaptureDevicesSendMessage(); + getRenderDevicesSendMessage(); +} + +void LLVoiceClient::daemonDied() +{ + // The daemon died, so the connection is gone. Reset everything and start over. + llwarns << "Connection to vivox daemon lost. Resetting state."<< llendl; + + closeSocket(); + removeAllParticipants(); + + // Try to relaunch the daemon + setState(stateDisabled); +} + +void LLVoiceClient::giveUp() +{ + // All has failed. Clean up and stop trying. + closeSocket(); + removeAllParticipants(); + + setState(stateJail); +} + +void LLVoiceClient::sendPositionalUpdate(void) +{ + std::ostringstream stream; + + if(mSpatialCoordsDirty) + { + LLVector3 l, u, a; + + // Always send both speaker and listener positions together. + stream << "" + << "" << mSessionHandle << ""; + + stream << ""; + + l = mAvatarRot.getLeftRow(); + u = mAvatarRot.getUpRow(); + a = mAvatarRot.getFwdRow(); + +// llinfos << "Sending speaker position " << mSpeakerPosition << llendl; + + stream + << "" + << "" << mAvatarPosition[VX] << "" + << "" << mAvatarPosition[VZ] << "" + << "" << mAvatarPosition[VY] << "" + << "" + << "" + << "" << mAvatarVelocity[VX] << "" + << "" << mAvatarVelocity[VZ] << "" + << "" << mAvatarVelocity[VY] << "" + << "" + << "" + << "" << l.mV[VX] << "" + << "" << u.mV[VX] << "" + << "" << a.mV[VX] << "" + << "" + << "" + << "" << l.mV[VZ] << "" + << "" << u.mV[VY] << "" + << "" << a.mV[VZ] << "" + << "" + << "" + << "" << l.mV [VY] << "" + << "" << u.mV [VZ] << "" + << "" << a.mV [VY] << "" + << ""; + + stream << ""; + + stream << ""; + + LLVector3d earPosition; + LLVector3 earVelocity; + LLMatrix3 earRot; + + switch(mEarLocation) + { + case earLocCamera: + default: + earPosition = mCameraPosition; + earVelocity = mCameraVelocity; + earRot = mCameraRot; + break; + + case earLocAvatar: + earPosition = mAvatarPosition; + earVelocity = mAvatarVelocity; + earRot = mAvatarRot; + break; + + case earLocMixed: + earPosition = mAvatarPosition; + earVelocity = mAvatarVelocity; + earRot = mCameraRot; + break; + } + + l = earRot.getLeftRow(); + u = earRot.getUpRow(); + a = earRot.getFwdRow(); + +// llinfos << "Sending listener position " << mListenerPosition << llendl; + + stream + << "" + << "" << earPosition[VX] << "" + << "" << earPosition[VZ] << "" + << "" << earPosition[VY] << "" + << "" + << "" + << "" << earVelocity[VX] << "" + << "" << earVelocity[VZ] << "" + << "" << earVelocity[VY] << "" + << "" + << "" + << "" << l.mV[VX] << "" + << "" << u.mV[VX] << "" + << "" << a.mV[VX] << "" + << "" + << "" + << "" << l.mV[VZ] << "" + << "" << u.mV[VY] << "" + << "" << a.mV[VZ] << "" + << "" + << "" + << "" << l.mV [VY] << "" + << "" << u.mV [VZ] << "" + << "" << a.mV [VY] << "" + << ""; + + stream << ""; + + stream << "\n\n\n"; + } + + if(mPTTDirty) + { + // Send a local mute command. + // NOTE that the state of "PTT" is the inverse of "local mute". + // (i.e. when PTT is true, we send a mute command with "false", and vice versa) + +// llinfos << "Sending MuteLocalMic command with parameter " << (mPTT?"false":"true") << llendl; + + stream << "" + << "" << mConnectorHandle << "" + << "" << (mPTT?"false":"true") << "" + << "\n\n\n"; + + } + + if(mVolumeDirty) + { + participantMap::iterator iter = mParticipantMap.begin(); + + for(; iter != mParticipantMap.end(); iter++) + { + participantState *p = iter->second; + + if(p->mVolumeDirty) + { + int volume = p->mOnMuteList?0:p->mUserVolume; + + llinfos << "Setting volume for avatar " << p->mAvatarID << " to " << volume << llendl; + + // Send a mute/unumte command for the user (actually "volume for me"). + stream << "" + << "" << mSessionHandle << "" + << "" << p->mURI << "" + << "" << volume << "" + << "\n\n\n"; + + p->mVolumeDirty = false; + } + } + } + + if(mSpeakerMuteDirty) + { + const char *muteval = ((mSpeakerVolume == -100)?"true":"false"); + llinfos << "Setting speaker mute to " << muteval << llendl; + + stream << "" + << "" << mConnectorHandle << "" + << "" << muteval << "" + << "\n\n\n"; + } + + if(mSpeakerVolumeDirty) + { + llinfos << "Setting speaker volume to " << mSpeakerVolume << llendl; + + stream << "" + << "" << mConnectorHandle << "" + << "" << mSpeakerVolume << "" + << "\n\n\n"; + } + + if(mMicVolumeDirty) + { + llinfos << "Setting mic volume to " << mMicVolume << llendl; + + stream << "" + << "" << mConnectorHandle << "" + << "" << mMicVolume << "" + << "\n\n\n"; + } + + + // MBW -- XXX -- Maybe check to make sure the capture/render devices are in the current list here? + if(mCaptureDeviceDirty) + { + buildSetCaptureDevice(stream); + } + + if(mRenderDeviceDirty) + { + buildSetRenderDevice(stream); + } + + mSpatialCoordsDirty = false; + mPTTDirty = false; + mVolumeDirty = false; + mSpeakerVolumeDirty = false; + mMicVolumeDirty = false; + mSpeakerMuteDirty = false; + mCaptureDeviceDirty = false; + mRenderDeviceDirty = false; + + if(!stream.str().empty()) + { + writeString(stream.str()); + } +} + +void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream) +{ + llinfos << "Setting input device = \"" << mCaptureDevice << "\"" << llendl; + + stream + << "" + << "" << mCaptureDevice << "" + << "" + << "\n\n\n"; +} + +void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream) +{ + llinfos << "Setting output device = \"" << mRenderDevice << "\"" << llendl; + + stream + << "" + << "" << mRenderDevice << "" + << "" + << "\n\n\n"; +} + +///////////////////////////// +// Response/Event handlers + +void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle) +{ + if(statusCode != 0) + { + llwarns << "Connector.Create response failure: " << statusString << llendl; + setState(stateConnectorFailed); + } + else + { + // Connector created, move forward. + mConnectorHandle = connectorHandle; + if(getState() == stateConnectorStarting) + { + setState(stateConnectorStarted); + } + } +} + +void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle) +{ + llinfos << "Account.Login response (" << statusCode << "): " << statusString << llendl; + + // Status code of 20200 means "bad password". We may want to special-case that at some point. + + if ( statusCode == 401 ) + { + // Login failure which is probably caused by the delay after a user's password being updated. + llinfos << "Account.Login response failure (" << statusCode << "): " << statusString << llendl; + setState(stateLoginRetry); + } + else if(statusCode != 0) + { + llwarns << "Account.Login response failure (" << statusCode << "): " << statusString << llendl; + setState(stateLoginFailed); + } + else + { + // Login succeeded, move forward. + mAccountHandle = accountHandle; + // MBW -- XXX -- This needs to wait until the LoginStateChangeEvent is received. +// if(getState() == stateLoggingIn) +// { +// setState(stateLoggedIn); +// } + } +} + +void LLVoiceClient::channelGetListResponse(int statusCode, std::string &statusString) +{ + if(statusCode != 0) + { + llwarns << "Account.ChannelGetList response failure: " << statusString << llendl; + switchChannel(); + } + else + { + // Got the channel list, try to do a lookup. + std::string uri = findChannelURI(mChannelName); + if(uri.empty()) + { + // Lookup failed, can't join a channel for this area. + llinfos << "failed to map channel name: " << mChannelName << llendl; + } + else + { + // We have a sip URL for this area. + llinfos << "mapped channel " << mChannelName << " to URI "<< uri << llendl; + } + + // switchChannel with an empty uri string will do the right thing (leave channel and not rejoin) + switchChannel(uri); + } +} + +void LLVoiceClient::sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle) +{ + if(statusCode != 0) + { + llwarns << "Session.Create response failure (" << statusCode << "): " << statusString << llendl; +// if(statusCode == 1015) +// { +// if(getState() == stateJoiningSession) +// { +// // this happened during a real join. Going to sessionTerminated should cause a retry in appropriate cases. +// llwarns << "session handle \"" << sessionHandle << "\", mSessionStateEventHandle \"" << mSessionStateEventHandle << "\""<< llendl; +// if(!sessionHandle.empty()) +// { +// // This session is bad. Terminate it. +// mSessionHandle = sessionHandle; +// sessionTerminateByHandle(sessionHandle); +// setState(stateLeavingSession); +// } +// else if(!mSessionStateEventHandle.empty()) +// { +// mSessionHandle = mSessionStateEventHandle; +// sessionTerminateByHandle(mSessionStateEventHandle); +// setState(stateLeavingSession); +// } +// else +// { +// setState(stateSessionTerminated); +// } +// } +// else +// { +// // We didn't think we were in the middle of a join. Don't change state. +// llwarns << "Not in stateJoiningSession, ignoring" << llendl; +// } +// } +// else + { + mVivoxErrorStatusCode = statusCode; + mVivoxErrorStatusString = statusString; + setState(stateJoinSessionFailed); + } + } + else + { + llinfos << "Session.Create response received (success), session handle is " << sessionHandle << llendl; + if(getState() == stateJoiningSession) + { + // This is also grabbed in the SessionStateChangeEvent handler, but it might be useful to have it early... + mSessionHandle = sessionHandle; + } + else + { + // We should never get a session.create response in any state except stateJoiningSession. Things are out of sync. Kill this session. + sessionTerminateByHandle(sessionHandle); + } + } +} + +void LLVoiceClient::sessionConnectResponse(int statusCode, std::string &statusString) +{ + if(statusCode != 0) + { + llwarns << "Session.Connect response failure (" << statusCode << "): " << statusString << llendl; +// if(statusCode == 1015) +// { +// llwarns << "terminating existing session" << llendl; +// sessionTerminate(); +// } +// else + { + mVivoxErrorStatusCode = statusCode; + mVivoxErrorStatusString = statusString; + setState(stateJoinSessionFailed); + } + } + else + { + llinfos << "Session.Connect response received (success)" << llendl; + } +} + +void LLVoiceClient::sessionTerminateResponse(int statusCode, std::string &statusString) +{ + if(statusCode != 0) + { + llwarns << "Session.Terminate response failure: (" << statusCode << "): " << statusString << llendl; + if(getState() == stateLeavingSession) + { + // This is probably "(404): Server reporting Failure. Not a member of this conference." + // Do this so we don't get stuck. + setState(stateSessionTerminated); + } + } + +} + +void LLVoiceClient::logoutResponse(int statusCode, std::string &statusString) +{ + if(statusCode != 0) + { + llwarns << "Account.Logout response failure: " << statusString << llendl; + // MBW -- XXX -- Should this ever fail? do we care if it does? + } + + if(getState() == stateLoggingOut) + { + setState(stateLoggedOut); + } +} + +void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statusString) +{ + if(statusCode != 0) + { + llwarns << "Connector.InitiateShutdown response failure: " << statusString << llendl; + // MBW -- XXX -- Should this ever fail? do we care if it does? + } + + mConnected = false; + + if(getState() == stateConnectorStopping) + { + setState(stateConnectorStopped); + } +} + +void LLVoiceClient::sessionStateChangeEvent( + std::string &uriString, + int statusCode, + std::string &statusString, + std::string &sessionHandle, + int state, + bool isChannel, + std::string &nameString) +{ + switch(state) + { + case 4: // I see this when joining the session + llinfos << "joined session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << llendl; + + // Session create succeeded, move forward. + mSessionStateEventHandle = sessionHandle; + mSessionStateEventURI = uriString; + if(sessionHandle == mSessionHandle) + { + // This is the session we're joining. + if(getState() == stateJoiningSession) + { + setState(stateSessionJoined); + //RN: the uriString being returned by vivox here is actually your account uri, not the channel + // you are attempting to join, so ignore it + //llinfos << "received URI " << uriString << "(previously " << mSessionURI << ")" << llendl; + //mSessionURI = uriString; + } + } + else if(sessionHandle == mNextSessionHandle) + { +// llinfos << "received URI " << uriString << ", name " << nameString << " for next session (handle " << mNextSessionHandle << ")" << llendl; + } + else + { + llwarns << "joining unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << llendl; + // MBW -- XXX -- Should we send a Session.Terminate here? + } + + break; + case 5: // I see this when leaving the session + llinfos << "left session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << llendl; + + // Set the session handle to the empty string. If we get back to stateJoiningSession, we'll want to wait for the new session handle. + if(sessionHandle == mSessionHandle) + { + // MBW -- XXX -- I think this is no longer necessary, now that we've got mNextSessionURI/mNextSessionHandle + // mSessionURI.clear(); + // clear the session handle here just for sanity. + mSessionHandle.clear(); + if(mSessionResetOnClose) + { + mSessionResetOnClose = false; + mNonSpatialChannel = false; + mNextSessionSpatial = true; + parcelChanged(); + } + + removeAllParticipants(); + + switch(getState()) + { + case stateJoiningSession: + case stateSessionJoined: + case stateRunning: + case stateLeavingSession: + case stateJoinSessionFailed: + case stateJoinSessionFailedWaiting: + // normal transition + llinfos << "left session " << sessionHandle << "in state " << state2string(getState()) << llendl; + setState(stateSessionTerminated); + break; + + case stateSessionTerminated: + // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state. + llwarns << "left session " << sessionHandle << "in state " << state2string(getState()) << llendl; + break; + + default: + llwarns << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << llendl; + setState(stateSessionTerminated); + break; + } + + // store status values for later notification of observers + mVivoxErrorStatusCode = statusCode; + mVivoxErrorStatusString = statusString; + } + else + { + llinfos << "leaving unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << llendl; + } + + mSessionStateEventHandle.clear(); + mSessionStateEventURI.clear(); + break; + default: + llwarns << "unknown state: " << state << llendl; + break; + } +} + +void LLVoiceClient::loginStateChangeEvent( + std::string &accountHandle, + int statusCode, + std::string &statusString, + int state) +{ + llinfos << "state is " << state << llendl; + /* + According to Mike S., status codes for this event are: + login_state_logged_out=0, + login_state_logged_in = 1, + login_state_logging_in = 2, + login_state_logging_out = 3, + login_state_resetting = 4, + login_state_error=100 + */ + + switch(state) + { + case 1: + if(getState() == stateLoggingIn) + { + setState(stateLoggedIn); + } + break; + + default: +// llwarns << "unknown state: " << state << llendl; + break; + } +} + +void LLVoiceClient::sessionNewEvent( + std::string &accountHandle, + std::string &eventSessionHandle, + int state, + std::string &nameString, + std::string &uriString) +{ +// llinfos << "state is " << state << llendl; + + switch(state) + { + case 0: + { + llinfos << "session handle = " << eventSessionHandle << ", name = " << nameString << ", uri = " << uriString << llendl; + + LLUUID caller_id; + if(IDFromName(nameString, caller_id)) + { + gIMMgr->inviteToSession(LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, caller_id), + LLString::null, + caller_id, + LLString::null, + IM_SESSION_P2P_INVITE, + eventSessionHandle); + } + else + { + llwarns << "Could not generate caller id from uri " << uriString << llendl; + } + } + break; + + default: + llwarns << "unknown state: " << state << llendl; + break; + } +} + +void LLVoiceClient::participantStateChangeEvent( + std::string &uriString, + int statusCode, + std::string &statusString, + int state, + std::string &nameString, + std::string &displayNameString, + int participantType) +{ + participantState *participant = NULL; + llinfos << "state is " << state << llendl; + + switch(state) + { + case 7: // I see this when a participant joins + participant = addParticipant(uriString); + if(participant) + { + participant->mName = nameString; + llinfos << "added participant \"" << participant->mName + << "\" (" << participant->mAvatarID << ")"<< llendl; + } + break; + case 9: // I see this when a participant leaves + participant = findParticipant(uriString); + if(participant) + { + removeParticipant(participant); + } + break; + default: +// llwarns << "unknown state: " << state << llendl; + break; + } +} + +void LLVoiceClient::participantPropertiesEvent( + std::string &uriString, + int statusCode, + std::string &statusString, + bool isLocallyMuted, + bool isModeratorMuted, + bool isSpeaking, + int volume, + F32 energy) +{ + participantState *participant = findParticipant(uriString); + if(participant) + { + participant->mPTT = !isLocallyMuted; + participant->mIsSpeaking = isSpeaking; + if (isSpeaking) + { + participant->mSpeakingTimeout.reset(); + } + participant->mPower = energy; + participant->mVolume = volume; + } + else + { + llwarns << "unknown participant: " << uriString << llendl; + } +} + +void LLVoiceClient::auxAudioPropertiesEvent(F32 energy) +{ +// llinfos << "got energy " << energy << llendl; + mTuningEnergy = energy; +} + +void LLVoiceClient::muteListChanged() +{ + // The user's mute list has been updated. Go through the current participant list and sync it with the mute list. + + participantMap::iterator iter = mParticipantMap.begin(); + + for(; iter != mParticipantMap.end(); iter++) + { + participantState *p = iter->second; + + // Check to see if this participant is on the mute list already + updateMuteState(p); + } +} + +///////////////////////////// +// Managing list of participants +LLVoiceClient::participantState::participantState(const std::string &uri) : + mURI(uri), mPTT(false), mIsSpeaking(false), mPower(0.0), mServiceType(serviceTypeUnknown), + mOnMuteList(false), mUserVolume(100), mVolumeDirty(false), mAvatarIDValid(false) +{ +} + +LLVoiceClient::participantState *LLVoiceClient::addParticipant(const std::string &uri) +{ + participantState *result = NULL; + + participantMap::iterator iter = mParticipantMap.find(uri); + + if(iter != mParticipantMap.end()) + { + // Found a matching participant already in the map. + result = iter->second; + } + + if(!result) + { + // participant isn't already in one list or the other. + result = new participantState(uri); + mParticipantMap.insert(participantMap::value_type(uri, result)); + mParticipantMapChanged = true; + + // Try to do a reverse transform on the URI to get the GUID back. + { + LLUUID id; + if(IDFromName(uri, id)) + { + result->mAvatarIDValid = true; + result->mAvatarID = id; + + updateMuteState(result); + } + } + + llinfos << "participant \"" << result->mURI << "\" added." << llendl; + } + + return result; +} + +void LLVoiceClient::updateMuteState(participantState *p) +{ + if(p->mAvatarIDValid) + { + bool isMuted = gMuteListp->isMuted(p->mAvatarID, LLMute::flagVoiceChat); + if(p->mOnMuteList != isMuted) + { + p->mOnMuteList = isMuted; + p->mVolumeDirty = true; + mVolumeDirty = true; + } + } +} + +void LLVoiceClient::removeParticipant(LLVoiceClient::participantState *participant) +{ + if(participant) + { + participantMap::iterator iter = mParticipantMap.find(participant->mURI); + + llinfos << "participant \"" << participant->mURI << "\" (" << participant->mAvatarID << ") removed." << llendl; + + mParticipantMap.erase(iter); + delete participant; + mParticipantMapChanged = true; + } +} + +void LLVoiceClient::removeAllParticipants() +{ + llinfos << "called" << llendl; + + while(!mParticipantMap.empty()) + { + removeParticipant(mParticipantMap.begin()->second); + } +} + +LLVoiceClient::participantMap *LLVoiceClient::getParticipantList(void) +{ + return &mParticipantMap; +} + + +LLVoiceClient::participantState *LLVoiceClient::findParticipant(const std::string &uri) +{ + participantState *result = NULL; + + // Don't find any participants if we're not connected. This is so that we don't continue to get stale data + // after the daemon dies. + if(mConnected) + { + participantMap::iterator iter = mParticipantMap.find(uri); + + if(iter != mParticipantMap.end()) + { + result = iter->second; + } + } + + return result; +} + + +LLVoiceClient::participantState *LLVoiceClient::findParticipantByAvatar(LLVOAvatar *avatar) +{ + participantState * result = NULL; + + // You'd think this would work, but it doesn't... +// std::string uri = sipURIFromAvatar(avatar); + + // Currently, the URI is just the account name. + std::string loginName = nameFromAvatar(avatar); + result = findParticipant(loginName); + + if(result != NULL) + { + if(!result->mAvatarIDValid) + { + result->mAvatarID = avatar->getID(); + result->mAvatarIDValid = true; + + // We just figured out the avatar ID, so the participant list has "changed" from the perspective of anyone who uses that to identify participants. + mParticipantMapChanged = true; + + updateMuteState(result); + } + + + } + + return result; +} + +LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID& id) +{ + participantState * result = NULL; + + // Currently, the URI is just the account name. + std::string loginName = nameFromID(id); + result = findParticipant(loginName); + + return result; +} + + +void LLVoiceClient::clearChannelMap(void) +{ + mChannelMap.clear(); +} + +void LLVoiceClient::addChannelMapEntry(std::string &name, std::string &uri) +{ +// llinfos << "Adding channel name mapping: " << name << " -> " << uri << llendl; + mChannelMap.insert(channelMap::value_type(name, uri)); +} + +std::string LLVoiceClient::findChannelURI(std::string &name) +{ + std::string result; + + channelMap::iterator iter = mChannelMap.find(name); + + if(iter != mChannelMap.end()) + { + result = iter->second; + } + + return result; +} + +void LLVoiceClient::parcelChanged() +{ + if(getState() >= stateLoggedIn) + { + // If the user is logged in, start a channel lookup. + llinfos << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << llendl; + + std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest"); + LLSD data; + data["method"] = "call"; + LLHTTPClient::post( + url, + data, + new LLVoiceClientCapResponder); + } + else + { + // The transition to stateLoggedIn needs to kick this off again. + llinfos << "not logged in yet, deferring" << llendl; + } +} + +void LLVoiceClient::switchChannel( + std::string uri, + bool spatial, + bool noReconnect, + std::string hash) +{ + bool needsSwitch = false; + + llinfos << "called in state " << state2string(getState()) << " with uri \"" << uri << "\"" << llendl; + + switch(getState()) + { + case stateJoinSessionFailed: + case stateJoinSessionFailedWaiting: + case stateNoChannel: + // Always switch to the new URI from these states. + needsSwitch = true; + break; + + default: + if(mSessionTerminateRequested) + { + // If a terminate has been requested, we need to compare against where the URI we're already headed to. + if(mNextSessionURI != uri) + needsSwitch = true; + } + else + { + // Otherwise, compare against the URI we're in now. + if(mSessionURI != uri) + needsSwitch = true; + } + break; + } + + if(needsSwitch) + { + mNextSessionURI = uri; + mNextSessionHash = hash; + mNextSessionHandle.clear(); + mNextP2PSessionURI.clear(); + mNextSessionSpatial = spatial; + mNextSessionNoReconnect = noReconnect; + + if(uri.empty()) + { + // Leave any channel we may be in + llinfos << "leaving channel" << llendl; + } + else + { + llinfos << "switching to channel " << uri << llendl; + } + + if(getState() <= stateNoChannel) + { + // We're already set up to join a channel, just needed to fill in the session URI + } + else + { + // State machine will come around and rejoin if uri/handle is not empty. + sessionTerminate(); + } + } +} + +void LLVoiceClient::joinSession(std::string handle, std::string uri) +{ + mNextSessionURI.clear(); + mNextSessionHash.clear(); + mNextP2PSessionURI = uri; + mNextSessionHandle = handle; + mNextSessionSpatial = false; + mNextSessionNoReconnect = false; + + if(getState() <= stateNoChannel) + { + // We're already set up to join a channel, just needed to fill in the session handle + } + else + { + // State machine will come around and rejoin if uri/handle is not empty. + sessionTerminate(); + } +} + +void LLVoiceClient::setNonSpatialChannel( + const std::string &uri, + const std::string &credentials) +{ + switchChannel(uri, false, false, credentials); +} + +void LLVoiceClient::setSpatialChannel( + const std::string &uri, + const std::string &credentials) +{ + mSpatialSessionURI = uri; + mAreaVoiceDisabled = mSpatialSessionURI.empty(); + + llinfos << "got spatial channel uri: \"" << uri << "\"" << llendl; + + if(mNonSpatialChannel || !mNextSessionSpatial) + { + // User is in a non-spatial chat or joining a non-spatial chat. Don't switch channels. + llinfos << "in non-spatial chat, not switching channels" << llendl; + } + else + { + switchChannel(mSpatialSessionURI, true, false, credentials); + } +} + +void LLVoiceClient::callUser(LLUUID &uuid) +{ + std::string userURI = sipURIFromID(uuid); + + switchChannel(userURI, false, true); +} + +void LLVoiceClient::answerInvite(std::string &sessionHandle, LLUUID& other_user_id) +{ + joinSession(sessionHandle, sipURIFromID(other_user_id)); +} + +void LLVoiceClient::declineInvite(std::string &sessionHandle) +{ + sessionTerminateByHandle(sessionHandle); +} + +void LLVoiceClient::leaveNonSpatialChannel() +{ + switchChannel(mSpatialSessionURI); +} + +std::string LLVoiceClient::getCurrentChannel() +{ + if((getState() == stateRunning) && !mSessionTerminateRequested) + { + return mSessionURI; + } + + return ""; +} + +bool LLVoiceClient::inProximalChannel() +{ + bool result = false; + + if((getState() == stateRunning) && !mSessionTerminateRequested) + { + result = !mNonSpatialChannel; + } + + return result; +} + +std::string LLVoiceClient::sipURIFromID(const LLUUID &id) +{ + std::string result; + result = "sip:"; + result += nameFromID(id); + result += "@"; + result += mAccountServerName; + + return result; +} + +std::string LLVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar) +{ + std::string result; + if(avatar) + { + result = "sip:"; + result += nameFromID(avatar->getID()); + result += "@"; + result += mAccountServerName; + } + + return result; +} + +std::string LLVoiceClient::nameFromAvatar(LLVOAvatar *avatar) +{ + std::string result; + if(avatar) + { + result = nameFromID(avatar->getID()); + } + return result; +} + +std::string LLVoiceClient::nameFromID(const LLUUID &uuid) +{ + std::string result; + U8 rawuuid[UUID_BYTES + 1]; + uuid.toCompressedString((char*)rawuuid); + + // Prepending this apparently prevents conflicts with reserved names inside the vivox and diamondware code. + result = "x"; + + // Base64 encode and replace the pieces of base64 that are less compatible + // with e-mail local-parts. + // See RFC-4648 "Base 64 Encoding with URL and Filename Safe Alphabet" + result += LLBase64::encode(rawuuid, UUID_BYTES); + LLString::replaceChar(result, '+', '-'); + LLString::replaceChar(result, '/', '_'); + + // If you need to transform a GUID to this form on the Mac OS X command line, this will do so: + // echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-') + + return result; +} + +bool LLVoiceClient::IDFromName(const std::string name, LLUUID &uuid) +{ + bool result = false; + + // This will only work if the name is of the proper form. + // As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is: + // "xFnPP04IpREWNkuw1cOXlhw==" + + if((name.size() == 25) && (name[0] == 'x') && (name[23] == '=') && (name[24] == '=')) + { + // The name appears to have the right form. + + // Reverse the transforms done by nameFromID + std::string temp = name; + LLString::replaceChar(temp, '-', '+'); + LLString::replaceChar(temp, '_', '/'); + + U8 rawuuid[UUID_BYTES + 1]; + int len = apr_base64_decode_binary(rawuuid, temp.c_str() + 1); + if(len == UUID_BYTES) + { + // The decode succeeded. Stuff the bits into the result's UUID + // MBW -- XXX -- there's no analogue of LLUUID::toCompressedString that allows you to set a UUID from binary data. + // The data field is public, so we cheat thusly: + memcpy(uuid.mData, rawuuid, UUID_BYTES); + result = true; + } + } + + return result; +} + +std::string LLVoiceClient::displayNameFromAvatar(LLVOAvatar *avatar) +{ + return avatar->getFullname(); +} + +std::string LLVoiceClient::sipURIFromName(std::string &name) +{ + std::string result; + result = "sip:"; + result += name; + result += "@"; + result += mAccountServerName; + +// LLString::toLower(result); + + return result; +} + +///////////////////////////// +// Sending updates of current state + +void LLVoiceClient::enforceTether(void) +{ + LLVector3d tethered = mCameraRequestedPosition; + + // constrain 'tethered' to within 50m of mAvatarPosition. + { + F32 max_dist = 50.0f; + LLVector3d camera_offset = mCameraRequestedPosition - mAvatarPosition; + F32 camera_distance = (F32)camera_offset.magVec(); + if(camera_distance > max_dist) + { + tethered = mAvatarPosition + + (max_dist / camera_distance) * camera_offset; + } + } + + if(dist_vec(mCameraPosition, tethered) > 0.1) + { + mCameraPosition = tethered; + mSpatialCoordsDirty = true; + } +} + +void LLVoiceClient::setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot) +{ + mCameraRequestedPosition = position; + + if(mCameraVelocity != velocity) + { + mCameraVelocity = velocity; + mSpatialCoordsDirty = true; + } + + if(mCameraRot != rot) + { + mCameraRot = rot; + mSpatialCoordsDirty = true; + } +} + +void LLVoiceClient::setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot) +{ + if(dist_vec(mAvatarPosition, position) > 0.1) + { + mAvatarPosition = position; + mSpatialCoordsDirty = true; + } + + if(mAvatarVelocity != velocity) + { + mAvatarVelocity = velocity; + mSpatialCoordsDirty = true; + } + + if(mAvatarRot != rot) + { + mAvatarRot = rot; + mSpatialCoordsDirty = true; + } +} + +bool LLVoiceClient::channelFromRegion(LLViewerRegion *region, std::string &name) +{ + bool result = false; + + if(region) + { + name = region->getName(); + } + + if(!name.empty()) + result = true; + + return result; +} + +void LLVoiceClient::leaveChannel(void) +{ + if(getState() == stateRunning) + { +// llinfos << "leaving channel for teleport/logout" << llendl; + mChannelName.clear(); + sessionTerminate(); + } +} + +void LLVoiceClient::setMuteMic(bool muted) +{ + mMuteMic = muted; +} + +void LLVoiceClient::setUserPTTState(bool ptt) +{ + mUserPTTState = ptt; +} + +bool LLVoiceClient::getUserPTTState() +{ + return mUserPTTState; +} + +void LLVoiceClient::toggleUserPTTState(void) +{ + mUserPTTState = !mUserPTTState; +} + +void LLVoiceClient::setVoiceEnabled(bool enabled) +{ + if (enabled != mVoiceEnabled) + { + mVoiceEnabled = enabled; + if (enabled) + { + LLVoiceChannel::getCurrentVoiceChannel()->activate(); + } + else + { + // for now, leave active channel, to auto join when turning voice back on + //LLVoiceChannel::getCurrentVoiceChannel->deactivate(); + } + } +} + +bool LLVoiceClient::voiceEnabled() +{ + return gSavedSettings.getBOOL("EnableVoiceChat") && !gDisableVoice; +} + +void LLVoiceClient::setUsePTT(bool usePTT) +{ + if(usePTT && !mUsePTT) + { + // When the user turns on PTT, reset the current state. + mUserPTTState = false; + } + mUsePTT = usePTT; +} + +void LLVoiceClient::setPTTIsToggle(bool PTTIsToggle) +{ + if(!PTTIsToggle && mPTTIsToggle) + { + // When the user turns off toggle, reset the current state. + mUserPTTState = false; + } + + mPTTIsToggle = PTTIsToggle; +} + + +void LLVoiceClient::setPTTKey(std::string &key) +{ + if(key == "MiddleMouse") + { + mPTTIsMiddleMouse = true; + } + else + { + mPTTIsMiddleMouse = false; + if(!LLKeyboard::keyFromString(key, &mPTTKey)) + { + // If the call failed, don't match any key. + key = KEY_NONE; + } + } +} + +void LLVoiceClient::setEarLocation(S32 loc) +{ + if(mEarLocation != loc) + { + llinfos << "Setting mEarLocation to " << loc << llendl; + + mEarLocation = loc; + mSpatialCoordsDirty = true; + } +} + +void LLVoiceClient::setVoiceVolume(F32 volume) +{ + int scaledVolume = ((int)(volume * 100.0f)) - 100; + if(scaledVolume != mSpeakerVolume) + { + if((scaledVolume == -100) || (mSpeakerVolume == -100)) + { + mSpeakerMuteDirty = true; + } + + mSpeakerVolume = scaledVolume; + mSpeakerVolumeDirty = true; + } +} + +void LLVoiceClient::setMicGain(F32 volume) +{ + int scaledVolume = ((int)(volume * 100.0f)) - 100; + if(scaledVolume != mMicVolume) + { + mMicVolume = scaledVolume; + mMicVolumeDirty = true; + } +} + +void LLVoiceClient::setVivoxDebugServerName(std::string &serverName) +{ + if(!mAccountServerName.empty()) + { + // The name has been filled in already, which means we know whether we're connecting to agni or not. + if(!sConnectingToAgni) + { + // Only use the setting if we're connecting to a development grid -- always use bhr when on agni. + mAccountServerName = serverName; + } + } +} + +void LLVoiceClient::keyDown(KEY key, MASK mask) +{ +// llinfos << "key is " << LLKeyboard::stringFromKey(key) << llendl; + + if (gKeyboard->getKeyRepeated(key)) + { + // ignore auto-repeat keys + return; + } + + if(!mPTTIsMiddleMouse) + { + if(mPTTIsToggle) + { + if(key == mPTTKey) + { + toggleUserPTTState(); + } + } + else if(mPTTKey != KEY_NONE) + { + setUserPTTState(gKeyboard->getKeyDown(mPTTKey)); + } + } +} +void LLVoiceClient::keyUp(KEY key, MASK mask) +{ + if(!mPTTIsMiddleMouse) + { + if(!mPTTIsToggle && (mPTTKey != KEY_NONE)) + { + setUserPTTState(gKeyboard->getKeyDown(mPTTKey)); + } + } +} +void LLVoiceClient::middleMouseState(bool down) +{ + if(mPTTIsMiddleMouse) + { + if(mPTTIsToggle) + { + if(down) + { + toggleUserPTTState(); + } + } + else + { + setUserPTTState(down); + } + } +} + +///////////////////////////// +// Accessors for data related to nearby speakers +BOOL LLVoiceClient::getVoiceEnabled(const LLUUID& id) +{ + BOOL result = FALSE; + participantState *participant = findParticipantByID(id); + if(participant) + { + // I'm not sure what the semantics of this should be. + // For now, if we have any data about the user that came through the chat channel, assume they're voice-enabled. + result = TRUE; + } + + return result; +} + +BOOL LLVoiceClient::getIsSpeaking(const LLUUID& id) +{ + BOOL result = FALSE; + + participantState *participant = findParticipantByID(id); + if(participant) + { + if (participant->mSpeakingTimeout.getElapsedTimeF32() > SPEAKING_TIMEOUT) + { + participant->mIsSpeaking = FALSE; + } + result = participant->mIsSpeaking; + } + + return result; +} + +F32 LLVoiceClient::getCurrentPower(const LLUUID& id) +{ + F32 result = 0; + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mPower; + } + + return result; +} + + +LLString LLVoiceClient::getDisplayName(const LLUUID& id) +{ + LLString result; + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mDisplayName; + } + + return result; +} + + +BOOL LLVoiceClient::getUsingPTT(const LLUUID& id) +{ + BOOL result = FALSE; + + participantState *participant = findParticipantByID(id); + if(participant) + { + // I'm not sure what the semantics of this should be. + // Does "using PTT" mean they're configured with a push-to-talk button? + // For now, we know there's no PTT mechanism in place, so nobody is using it. + } + + return result; +} + +BOOL LLVoiceClient::getPTTPressed(const LLUUID& id) +{ + BOOL result = FALSE; + + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mPTT; + } + + return result; +} + +BOOL LLVoiceClient::getOnMuteList(const LLUUID& id) +{ + BOOL result = FALSE; + + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mOnMuteList; + } + + return result; +} + +// External accessiors. Maps 0.0 to 1.0 to internal values 0-400 with .5 == 100 +// internal = 400 * external^2 +F32 LLVoiceClient::getUserVolume(const LLUUID& id) +{ + F32 result = 0.0f; + + participantState *participant = findParticipantByID(id); + if(participant) + { + S32 ires = participant->mUserVolume; // 0-400 + result = sqrtf(((F32)ires) / 400.f); + } + + return result; +} + +void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume) +{ + participantState *participant = findParticipantByID(id); + if (participant) + { + // volume can amplify by as much as 4x! + S32 ivol = (S32)(400.f * volume * volume); + participant->mUserVolume = llclamp(ivol, 0, 400); + participant->mVolumeDirty = TRUE; + mVolumeDirty = TRUE; + } +} + + + +LLVoiceClient::serviceType LLVoiceClient::getServiceType(const LLUUID& id) +{ + serviceType result = serviceTypeUnknown; + + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mServiceType; + } + + return result; +} + +std::string LLVoiceClient::getGroupID(const LLUUID& id) +{ + std::string result; + + participantState *participant = findParticipantByID(id); + if(participant) + { + result = participant->mGroupID; + } + + return result; +} + +BOOL LLVoiceClient::getAreaVoiceDisabled() +{ + return mAreaVoiceDisabled; +} + +void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) +{ + mObservers.insert(observer); +} + +void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer) +{ + mObservers.erase(observer); +} + +void LLVoiceClient::notifyObservers() +{ + for (observer_set_t::iterator it = mObservers.begin(); + it != mObservers.end(); + ) + { + LLVoiceClientParticipantObserver* observer = *it; + observer->onChange(); + // In case onChange() deleted an entry. + it = mObservers.upper_bound(observer); + } +} + +void LLVoiceClient::addStatusObserver(LLVoiceClientStatusObserver* observer) +{ + mStatusObservers.insert(observer); +} + +void LLVoiceClient::removeStatusObserver(LLVoiceClientStatusObserver* observer) +{ + mStatusObservers.erase(observer); +} + +void LLVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status) +{ + if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN) + { + switch(mVivoxErrorStatusCode) + { + case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break; + case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break; + } + + // Reset the error code to make sure it won't be reused later by accident. + mVivoxErrorStatusCode = 0; + } + + if (status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL + //NOT_FOUND || TEMPORARILY_UNAVAILABLE || REQUEST_TIMEOUT + && (mVivoxErrorStatusCode == 404 || mVivoxErrorStatusCode == 480 || mVivoxErrorStatusCode == 408)) + { + // call failed because other user was not available + // treat this as an error case + status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE; + + // Reset the error code to make sure it won't be reused later by accident. + mVivoxErrorStatusCode = 0; + } + + llinfos << " " << LLVoiceClientStatusObserver::status2string(status) << ", session URI " << mSessionURI << llendl; + + for (status_observer_set_t::iterator it = mStatusObservers.begin(); + it != mStatusObservers.end(); + ) + { + LLVoiceClientStatusObserver* observer = *it; + observer->onChange(status, mSessionURI, !mNonSpatialChannel); + // In case onError() deleted an entry. + it = mStatusObservers.upper_bound(observer); + } + +} + +//static +void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* user_data) +{ + participantState* statep = gVoiceClient->findParticipantByID(id); + + if (statep) + { + statep->mDisplayName = llformat("%s %s", first, last); + } + + gVoiceClient->notifyObservers(); +} + +class LLViewerParcelVoiceInfo : public LLHTTPNode +{ + virtual void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + //the parcel you are in has changed something about its + //voice information + + if ( input.has("body") ) + { + LLSD body = input["body"]; + + //body has "region_name" (str), "parcel_local_id"(int), + //"voice_credentials" (map). + + //body["voice_credentials"] has "channel_uri" (str), + //body["voice_credentials"] has "channel_credentials" (str) + if ( body.has("voice_credentials") ) + { + LLSD voice_credentials = body["voice_credentials"]; + std::string uri; + std::string credentials; + + if ( voice_credentials.has("channel_uri") ) + { + uri = voice_credentials["channel_uri"].asString(); + } + if ( voice_credentials.has("channel_credentials") ) + { + credentials = + voice_credentials["channel_credentials"].asString(); + } + + gVoiceClient->setSpatialChannel(uri, credentials); + } + } + } +}; + +class LLViewerRequiredVoiceVersion : public LLHTTPNode +{ + static BOOL sAlertedUser; + virtual void post( + LLHTTPNode::ResponsePtr response, + const LLSD& context, + const LLSD& input) const + { + //You received this messsage (most likely on region cross or + //teleport) + if ( input.has("body") && input["body"].has("major_version") ) + { + int major_voice_version = + input["body"]["major_version"].asInteger(); +// int minor_voice_version = +// input["body"]["minor_version"].asInteger(); + + if (gVoiceClient && + (major_voice_version > VOICE_MAJOR_VERSION) ) + { + if (!sAlertedUser) + { + //sAlertedUser = TRUE; + gViewerWindow->alertXml("VoiceVersionMismatch"); + gSavedSettings.setBOOL("EnableVoiceChat", FALSE); // toggles listener + } + } + } + } +}; +BOOL LLViewerRequiredVoiceVersion::sAlertedUser = FALSE; + +LLHTTPRegistration + gHTTPRegistrationMessageParcelVoiceInfo( + "/message/ParcelVoiceInfo"); + +LLHTTPRegistration + gHTTPRegistrationMessageRequiredVoiceVersion( + "/message/RequiredVoiceVersion"); diff --git a/linden/indra/newview/llvoiceclient.h b/linden/indra/newview/llvoiceclient.h new file mode 100644 index 0000000..f65aa58 --- /dev/null +++ b/linden/indra/newview/llvoiceclient.h @@ -0,0 +1,523 @@ +/** + * @file llvoiceclient.h + * @brief Declaration of LLVoiceClient class which is the interface to the voice client process. + * + * Copyright (c) 2001-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ +#ifndef LL_VOICE_CLIENT_H +#define LL_VOICE_CLIENT_H + +// This would create a circular reference -- just do a forward definition of necessary class names. +//#include "llvoavatar.h" +class LLVOAvatar; +class LLVivoxProtocolParser; + +#include "lliopipe.h" +#include "llpumpio.h" +#include "llchainio.h" +#include "lliosocket.h" +#include "v3math.h" +#include "llframetimer.h" +#include "llviewerregion.h" + +class LLVoiceClientParticipantObserver +{ +public: + virtual ~LLVoiceClientParticipantObserver() { } + virtual void onChange() = 0; +}; + +class LLVoiceClientStatusObserver +{ +public: + typedef enum e_voice_status_type + { + STATUS_LOGIN_RETRY, + STATUS_LOGGED_IN, + STATUS_JOINING, + STATUS_JOINED, + STATUS_LEFT_CHANNEL, + BEGIN_ERROR_STATUS, + ERROR_CHANNEL_FULL, + ERROR_CHANNEL_LOCKED, + ERROR_NOT_AVAILABLE, + ERROR_UNKNOWN + } EStatusType; + + virtual ~LLVoiceClientStatusObserver() { } + virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) = 0; + + static const char *status2string(EStatusType inStatus); +}; + +class LLVoiceClient: public LLSingleton +{ + LOG_CLASS(LLVoiceClient); + public: + LLVoiceClient(); + ~LLVoiceClient(); + + public: + static void init(LLPumpIO *pump); // Call this once at application startup (creates connector) + static void terminate(); // Call this to clean up during shutdown + + protected: + bool writeString(const std::string &str); + + public: + + enum serviceType + { + serviceTypeUnknown, // Unknown, returned if no data on the avatar is available + serviceTypeA, // spatialized local chat + serviceTypeB, // remote multi-party chat + serviceTypeC // one-to-one and small group chat + }; + static F32 OVERDRIVEN_POWER_LEVEL; + + ///////////////////////////// + // session control messages + void connect(); + + void connectorCreate(); + void connectorShutdown(); + + void requestVoiceAccountProvision(S32 retries = 3); + void userAuthorized( + const std::string& firstName, + const std::string& lastName, + const LLUUID &agentID); + void login(const std::string& accountName, const std::string &password); + void loginSendMessage(); + void logout(); + void logoutSendMessage(); + + void channelGetListSendMessage(); + void sessionCreateSendMessage(); + void sessionConnectSendMessage(); + void sessionTerminate(); + void sessionTerminateSendMessage(); + void sessionTerminateByHandle(std::string &sessionHandle); + + void getCaptureDevicesSendMessage(); + void getRenderDevicesSendMessage(); + + void clearCaptureDevices(); + void addCaptureDevice(const std::string& name); + void setCaptureDevice(const std::string& name); + + void clearRenderDevices(); + void addRenderDevice(const std::string& name); + void setRenderDevice(const std::string& name); + + void tuningStart(); + void tuningStop(); + bool inTuningMode(); + + void tuningRenderStartSendMessage(const std::string& name, bool loop); + void tuningRenderStopSendMessage(); + + void tuningCaptureStartSendMessage(int duration); + void tuningCaptureStopSendMessage(); + + void tuningSetMicVolume(float volume); + void tuningSetSpeakerVolume(float volume); + float tuningGetEnergy(void); + + // This returns true when it's safe to bring up the "device settings" dialog in the prefs. + // i.e. when the daemon is running and connected, and the device lists are populated. + bool deviceSettingsAvailable(); + + // Requery the vivox daemon for the current list of input/output devices. + // If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed + // (use this if you want to know when it's done). + // If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim. + void refreshDeviceLists(bool clearCurrentList = true); + + // Call this if the connection to the daemon terminates unexpectedly. It will attempt to reset everything and relaunch. + void daemonDied(); + + // Call this if we're just giving up on voice (can't provision an account, etc.). It will clean up and go away. + void giveUp(); + + ///////////////////////////// + // Response/Event handlers + void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle); + void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle); + void channelGetListResponse(int statusCode, std::string &statusString); + void sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle); + void sessionConnectResponse(int statusCode, std::string &statusString); + void sessionTerminateResponse(int statusCode, std::string &statusString); + void logoutResponse(int statusCode, std::string &statusString); + void connectorShutdownResponse(int statusCode, std::string &statusString); + + void loginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state); + void sessionNewEvent(std::string &accountHandle, std::string &eventSessionHandle, int state, std::string &nameString, std::string &uriString); + void sessionStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, std::string &sessionHandle, int state, bool isChannel, std::string &nameString); + void participantStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, int state, std::string &nameString, std::string &displayNameString, int participantType); + void participantPropertiesEvent(std::string &uriString, int statusCode, std::string &statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy); + void auxAudioPropertiesEvent(F32 energy); + + void muteListChanged(); + + ///////////////////////////// + // Sending updates of current state + void setCameraPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot); + void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLMatrix3 &rot); + bool channelFromRegion(LLViewerRegion *region, std::string &name); + void leaveChannel(void); // call this on logout or teleport begin + + + void setMuteMic(bool muted); // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state. + void setUserPTTState(bool ptt); + bool getUserPTTState(); + void toggleUserPTTState(void); + void setVoiceEnabled(bool enabled); + static bool voiceEnabled(); + void setUsePTT(bool usePTT); + void setPTTIsToggle(bool PTTIsToggle); + void setPTTKey(std::string &key); + void setEarLocation(S32 loc); + void setVoiceVolume(F32 volume); + void setMicGain(F32 volume); + void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal) + void setVivoxDebugServerName(std::string &serverName); + + // PTT key triggering + void keyDown(KEY key, MASK mask); + void keyUp(KEY key, MASK mask); + void middleMouseState(bool down); + + ///////////////////////////// + // Accessors for data related to nearby speakers + BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar + BOOL getIsSpeaking(const LLUUID& id); + F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is... + BOOL getPTTPressed(const LLUUID& id); // This is the inverse of the "locally muted" property. + BOOL getOnMuteList(const LLUUID& id); + F32 getUserVolume(const LLUUID& id); + LLString getDisplayName(const LLUUID& id); + + // MBW -- XXX -- Not sure how to get this data out of the TVC + BOOL getUsingPTT(const LLUUID& id); + serviceType getServiceType(const LLUUID& id); // type of chat the user is involved in (see bHear scope doc for definitions of A/B/C) + std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable) + + ///////////////////////////// + BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled. + // Use this to determine whether to show a "no speech" icon in the menu bar. + + struct participantState + { + public: + participantState(const std::string &uri); + std::string mURI; + std::string mName; + std::string mDisplayName; + bool mPTT; + bool mIsSpeaking; + LLFrameTimer mSpeakingTimeout; + F32 mLastSpokeTimestamp; + F32 mPower; + int mVolume; + serviceType mServiceType; + std::string mGroupID; + bool mOnMuteList; // true if this avatar is on the user's mute list (and should be muted) + int mUserVolume; + bool mVolumeDirty; // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed) + bool mAvatarIDValid; + LLUUID mAvatarID; + }; + typedef std::map participantMap; + + participantState *findParticipant(const std::string &uri); + participantState *findParticipantByAvatar(LLVOAvatar *avatar); + participantState *findParticipantByID(const LLUUID& id); + + participantMap *getParticipantList(void); + + void addObserver(LLVoiceClientParticipantObserver* observer); + void removeObserver(LLVoiceClientParticipantObserver* observer); + + void addStatusObserver(LLVoiceClientStatusObserver* observer); + void removeStatusObserver(LLVoiceClientStatusObserver* observer); + + static void onAvatarNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* user_data); + typedef std::vector deviceList; + + deviceList *getCaptureDevices(); + deviceList *getRenderDevices(); + + void setNonSpatialChannel( + const std::string &uri, + const std::string &credentials); + void setSpatialChannel( + const std::string &uri, + const std::string &credentials); + void callUser(LLUUID &uuid); + void answerInvite(std::string &sessionHandle, LLUUID& other_user_id); + void declineInvite(std::string &sessionHandle); + void leaveNonSpatialChannel(); + + // Returns the URI of the current channel, or an empty string if not currently in a channel. + // NOTE that it will return an empty string if it's in the process of joining a channel. + std::string getCurrentChannel(); + + // returns true iff the user is currently in a proximal (local spatial) channel. + // Note that gestures should only fire if this returns true. + bool inProximalChannel(); + + std::string sipURIFromID(const LLUUID &id); + + private: + + // internal state for a simple state machine. This is used to deal with the asynchronous nature of some of the messages. + // Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string(). + enum state + { + stateDisabled, // Voice is turned off. + stateStart, // Class is initialized, socket is created + stateDaemonLaunched, // Daemon has been launched + stateConnecting, // connect() call has been issued + stateIdle, // socket is connected, ready for messaging + stateConnectorStart, // connector needs to be started + stateConnectorStarting, // waiting for connector handle + stateConnectorStarted, // connector handle received + stateMicTuningNoLogin, // mic tuning before login + stateLoginRetry, // need to retry login (failed due to changing password) + stateLoginRetryWait, // waiting for retry timer + stateNeedsLogin, // send login request + stateLoggingIn, // waiting for account handle + stateLoggedIn, // account handle received + stateNoChannel, // + stateMicTuningLoggedIn, // mic tuning for a logged in user + stateSessionCreate, // need to send Session.Create command + stateSessionConnect, // need to send Session.Connect command + stateJoiningSession, // waiting for session handle + stateSessionJoined, // session handle received + stateRunning, // in session, steady state + stateLeavingSession, // waiting for terminate session response + stateSessionTerminated, // waiting for terminate session response + + stateLoggingOut, // waiting for logout response + stateLoggedOut, // logout response received + stateConnectorStopping, // waiting for connector stop + stateConnectorStopped, // connector stop received + + // We go to this state if the login fails because the account needs to be provisioned. + + // error states. No way to recover from these yet. + stateConnectorFailed, + stateConnectorFailedWaiting, + stateLoginFailed, + stateLoginFailedWaiting, + stateJoinSessionFailed, + stateJoinSessionFailedWaiting, + + stateJail // Go here when all else has failed. Nothing will be retried, we're done. + }; + + state mState; + bool mSessionTerminateRequested; + bool mNonSpatialChannel; + + void setState(state inState); + state getState(void) { return mState; }; + static const char *state2string(state inState); + + void stateMachine(); + static void idle(void *user_data); + + LLHost mDaemonHost; + LLSocket::ptr_t mSocket; + bool mConnected; + + void closeSocket(void); + + LLPumpIO *mPump; + friend class LLVivoxProtocolParser; + + std::string mAccountName; + std::string mAccountPassword; + std::string mAccountDisplayName; + std::string mAccountFirstName; + std::string mAccountLastName; + + std::string mNextP2PSessionURI; // URI of the P2P session to join next + std::string mNextSessionURI; // URI of the session to join next + std::string mNextSessionHandle; // Session handle of the session to join next + std::string mNextSessionHash; // Password hash for the session to join next + bool mNextSessionSpatial; // Will next session be a spatial chat? + bool mNextSessionNoReconnect; // Next session should not auto-reconnect (i.e. user -> user chat) + bool mNextSessionResetOnClose; // If this is true, go back to spatial chat when the next session terminates. + + std::string mSessionStateEventHandle; // session handle received in SessionStateChangeEvents + std::string mSessionStateEventURI; // session URI received in SessionStateChangeEvents + + bool mTuningMode; + float mTuningEnergy; + std::string mTuningAudioFile; + int mTuningMicVolume; + bool mTuningMicVolumeDirty; + int mTuningSpeakerVolume; + bool mTuningSpeakerVolumeDirty; + bool mTuningCaptureRunning; + + std::string mSpatialSessionURI; + + bool mSessionResetOnClose; + + int mVivoxErrorStatusCode; + std::string mVivoxErrorStatusString; + + std::string mChannelName; // Name of the channel to be looked up + bool mAreaVoiceDisabled; + std::string mSessionURI; // URI of the session we're in. + bool mSessionP2P; // true if this session is a p2p call + + S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings + std::string mCurrentRegionName; // Used to detect parcel boundary crossings + + std::string mConnectorHandle; // returned by "Create Connector" message + std::string mAccountHandle; // returned by login message + std::string mSessionHandle; // returned by ? + U32 mCommandCookie; + + std::string mAccountServerName; + std::string mAccountServerURI; + + int mLoginRetryCount; + + participantMap mParticipantMap; + bool mParticipantMapChanged; + + deviceList mCaptureDevices; + deviceList mRenderDevices; + + std::string mCaptureDevice; + std::string mRenderDevice; + bool mCaptureDeviceDirty; + bool mRenderDeviceDirty; + + participantState *addParticipant(const std::string &uri); + // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted. + // Take care not to use the pointer again after that. + void removeParticipant(participantState *participant); + void removeAllParticipants(); + + void updateMuteState(participantState *participant); + + typedef std::map channelMap; + channelMap mChannelMap; + + // These are used by the parser when processing a channel list response. + void clearChannelMap(void); + void addChannelMapEntry(std::string &name, std::string &uri); + std::string findChannelURI(std::string &name); + + // This should be called when the code detects we have changed parcels. + // It initiates the call to the server that gets the parcel channel. + void parcelChanged(); + + void switchChannel(std::string uri = "", bool spatial = true, bool noReconnect = false, std::string hash = ""); + void joinSession(std::string handle, std::string uri); + + std::string nameFromAvatar(LLVOAvatar *avatar); + std::string nameFromID(const LLUUID &id); + bool IDFromName(const std::string name, LLUUID &uuid); + std::string displayNameFromAvatar(LLVOAvatar *avatar); + std::string sipURIFromAvatar(LLVOAvatar *avatar); + std::string sipURIFromName(std::string &name); + + void sendPositionalUpdate(void); + + void buildSetCaptureDevice(std::ostringstream &stream); + void buildSetRenderDevice(std::ostringstream &stream); + + void enforceTether(void); + + bool mSpatialCoordsDirty; + + LLVector3d mCameraPosition; + LLVector3d mCameraRequestedPosition; + LLVector3 mCameraVelocity; + LLMatrix3 mCameraRot; + + LLVector3d mAvatarPosition; + LLVector3 mAvatarVelocity; + LLMatrix3 mAvatarRot; + + bool mPTTDirty; + bool mPTT; + + bool mUsePTT; + bool mPTTIsMiddleMouse; + KEY mPTTKey; + bool mPTTIsToggle; + bool mUserPTTState; + bool mMuteMic; + + // Set to true when the mute state of someone in the participant list changes. + // The code will have to walk the list to find the changed participant(s). + bool mVolumeDirty; + + enum + { + earLocCamera = 0, // ear at camera + earLocAvatar, // ear at avatar + earLocMixed // ear at avatar location/camera direction + }; + + S32 mEarLocation; + + bool mSpeakerVolumeDirty; + bool mSpeakerMuteDirty; + int mSpeakerVolume; + + int mMicVolume; + bool mMicVolumeDirty; + + bool mVoiceEnabled; + bool mWriteInProgress; + std::string mWriteString; + size_t mWriteOffset; + + LLTimer mUpdateTimer; + + typedef std::set observer_set_t; + observer_set_t mObservers; + + void notifyObservers(); + + typedef std::set status_observer_set_t; + status_observer_set_t mStatusObservers; + + void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status); +}; + +extern LLVoiceClient *gVoiceClient; + +#endif //LL_VOICE_CLIENT_H + + diff --git a/linden/indra/newview/llvoiceremotectrl.cpp b/linden/indra/newview/llvoiceremotectrl.cpp new file mode 100644 index 0000000..720eb17 --- /dev/null +++ b/linden/indra/newview/llvoiceremotectrl.cpp @@ -0,0 +1,180 @@ +/** + * @file llvoiceremotectrl.cpp + * @brief A remote control for voice chat + * + * Copyright (c) 2005-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llvoiceremotectrl.h" + +#include "llagent.h" +#include "llui.h" +#include "llbutton.h" +#include "llvieweruictrlfactory.h" +#include "llviewercontrol.h" +#include "llvoiceclient.h" +#include "llimpanel.h" +#include "llfloateractivespeakers.h" +#include "lliconctrl.h" + +LLVoiceRemoteCtrl::LLVoiceRemoteCtrl (const LLString& name) : LLPanel(name) +{ + setIsChrome(TRUE); + + gUICtrlFactory->buildPanel(this, "panel_voice_remote.xml"); + + mTalkBtn = LLUICtrlFactory::getButtonByName(this, "push_to_talk"); + mTalkBtn->setClickedCallback(onBtnTalkClicked); + mTalkBtn->setHeldDownCallback(onBtnTalkHeld); + mTalkBtn->setMouseUpCallback(onBtnTalkReleased); + + mTalkLockBtn = LLUICtrlFactory::getButtonByName(this, "ptt_lock"); + mTalkLockBtn->setClickedCallback(onBtnLock); + + mSpeakersBtn = LLUICtrlFactory::getButtonByName(this, "speakers_btn"); + mSpeakersBtn->setClickedCallback(onClickSpeakers); + + mIsFocusRoot = TRUE; +} + +LLVoiceRemoteCtrl::~LLVoiceRemoteCtrl() +{ +} + +void LLVoiceRemoteCtrl::draw() +{ + BOOL voice_active = FALSE; + LLVoiceChannel* channelp = LLVoiceChannel::getCurrentVoiceChannel(); + if (channelp) + { + voice_active = channelp->isActive(); + } + + mTalkBtn->setEnabled(voice_active); + mTalkLockBtn->setEnabled(voice_active); + +// if (voice_active) +// { +// mTalkBtn->setToolTip(""); +// mTalkLockBtn->setToolTip(""); +// } +// else +// { +// mTalkBtn->setToolTip(""); +// mTalkLockBtn->setToolTip(""); +// } + + // propagate ptt state to button display, + if (!mTalkBtn->hasMouseCapture()) + { + // not in push to talk mode, or push to talk is active means I'm talking + mTalkBtn->setToggleState(!gSavedSettings.getBOOL("PTTCurrentlyEnabled") || gVoiceClient->getUserPTTState()); + } + mSpeakersBtn->setToggleState(LLFloaterActiveSpeakers::instanceVisible(LLSD())); + mTalkLockBtn->setToggleState(!gSavedSettings.getBOOL("PTTCurrentlyEnabled")); + + LLUUID talk_blip_image_id; + if (gVoiceClient->getIsSpeaking(gAgent.getID())) + { + F32 voice_power = gVoiceClient->getCurrentPower(gAgent.getID()); + + if (voice_power > LLVoiceClient::OVERDRIVEN_POWER_LEVEL) + { + talk_blip_image_id = LLUUID(gViewerArt.getString("icn_voice_ptt-on-lvl3.tga")); + } + else + { + F32 power = gVoiceClient->getCurrentPower(gAgent.getID()); + S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); + + switch(icon_image_idx) + { + case 0: + talk_blip_image_id = LLUUID(gViewerArt.getString("icn_voice_ptt-on.tga")); + break; + case 1: + talk_blip_image_id = LLUUID(gViewerArt.getString("icn_voice_ptt-on-lvl1.tga")); + break; + case 2: + talk_blip_image_id = LLUUID(gViewerArt.getString("icn_voice_ptt-on-lvl2.tga")); + break; + } + } + } + else + { + talk_blip_image_id = LLUUID(gViewerArt.getString("icn_voice_ptt-off.tga")); + } + + LLIconCtrl* icon = LLUICtrlFactory::getIconByName(this, "voice_volume"); + if (icon) + { + icon->setImage(talk_blip_image_id); + } + + LLPanel::draw(); +} + +void LLVoiceRemoteCtrl::onBtnTalkClicked(void *user_data) +{ + // when in toggle mode, clicking talk button turns mic on/off + if (gSavedSettings.getBOOL("PushToTalkToggle")) + { + gVoiceClient->toggleUserPTTState(); + } +} + +void LLVoiceRemoteCtrl::onBtnTalkHeld(void *user_data) +{ + // when not in toggle mode, holding down talk button turns on mic + if (!gSavedSettings.getBOOL("PushToTalkToggle")) + { + gVoiceClient->setUserPTTState(true); + } +} + +void LLVoiceRemoteCtrl::onBtnTalkReleased(void* user_data) +{ + // when not in toggle mode, releasing talk button turns off mic + if (!gSavedSettings.getBOOL("PushToTalkToggle")) + { + gVoiceClient->setUserPTTState(false); + } +} + +void LLVoiceRemoteCtrl::onBtnLock(void* user_data) +{ + LLVoiceRemoteCtrl* remotep = (LLVoiceRemoteCtrl*)user_data; + + remotep->mTalkLockBtn->toggleState(); + gSavedSettings.setBOOL("PTTCurrentlyEnabled", !remotep->mTalkLockBtn->getToggleState()); +} + +void LLVoiceRemoteCtrl::onClickSpeakers(void *user_data) +{ + LLFloaterActiveSpeakers::toggleInstance(LLSD()); +} + diff --git a/linden/indra/newview/llvoiceremotectrl.h b/linden/indra/newview/llvoiceremotectrl.h new file mode 100644 index 0000000..46ed709 --- /dev/null +++ b/linden/indra/newview/llvoiceremotectrl.h @@ -0,0 +1,56 @@ +/** + * @file llvoiceremotectrl.h + * @brief A remote control for voice chat + * + * Copyright (c) 2005-2007, 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 + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#ifndef LL_LLVOICEREMOTECTRL_H +#define LL_LLVOICEREMOTECTRL_H + +#include "llpanel.h" + +class LLButton; + +class LLVoiceRemoteCtrl : public LLPanel +{ +public: + LLVoiceRemoteCtrl (const LLString& name); + virtual ~LLVoiceRemoteCtrl(); + + /*virtual*/ void draw(); + + static void onBtnLock(void* user_data); + static void onBtnTalkHeld(void *user_data); + static void onBtnTalkReleased(void* user_data); + static void onBtnTalkClicked(void* user_data); + static void onClickSpeakers(void *user_data); + +protected: + LLButton* mTalkBtn; + LLButton* mTalkLockBtn; + LLButton* mSpeakersBtn; +}; + +#endif // LL_LLVOICEREMOTECTRL_H diff --git a/linden/indra/newview/llvoicevisualizer.cpp b/linden/indra/newview/llvoicevisualizer.cpp new file mode 100644 index 0000000..fca2226 --- /dev/null +++ b/linden/indra/newview/llvoicevisualizer.cpp @@ -0,0 +1,431 @@ +//---------------------------------------------------------------------- +// Voice Visualizer +// author: JJ Ventrella +// (information about this stuff can be found in "llvoicevisualizer.h") +//---------------------------------------------------------------------- +#include "llviewerprecompiledheaders.h" +#include "llviewercontrol.h" +#include "llglheaders.h" +#include "llsphere.h" +#include "llvoicevisualizer.h" +#include "llviewercamera.h" +#include "llviewerobject.h" +#include "llimagegl.h" +#include "llviewerimage.h" +#include "llviewerimagelist.h" +#include "llvoiceclient.h" + +//brent's wave image +//29de489d-0491-fb00-7dab-f9e686d31e83 + + +//-------------------------------------------------------------------------------------- +// sound symbol constants +//-------------------------------------------------------------------------------------- +const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear +const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red +const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green +const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away +const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size +const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0 +const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves +const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves +const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold) +const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture +const F32 DOT_OPACITY = 0.7f; // how opaque the dot is +const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude + +//-------------------------------------------------------------------------------------- +// gesticulation constants +//-------------------------------------------------------------------------------------- +const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f; +const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f; + +//-------------------------------------------------------------------------------------- +// other constants +//-------------------------------------------------------------------------------------- +const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. +const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL + +//----------------------------------------------- +// constructor +//----------------------------------------------- +LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) +:LLHUDEffect( type ) +{ + mCurrentTime = mTimer.getTotalSeconds(); + mPreviousTime = mCurrentTime; + mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); + mSpeakingAmplitude = 0.0f; + mCurrentlySpeaking = false; + mVoiceEnabled = false; + mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; + mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; + mSoundSymbol.mActive = true; + mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); + + mTimer.reset(); + + LLUUID sound_level_img[] = + { + LLUUID(gSavedSettings.getString("VoiceImageLevel0")), + LLUUID(gSavedSettings.getString("VoiceImageLevel1")), + LLUUID(gSavedSettings.getString("VoiceImageLevel2")), + LLUUID(gSavedSettings.getString("VoiceImageLevel3")), + LLUUID(gSavedSettings.getString("VoiceImageLevel4")), + LLUUID(gSavedSettings.getString("VoiceImageLevel5")), + LLUUID(gSavedSettings.getString("VoiceImageLevel6")) + }; + + for (int i=0; igetLeftAxis() * DOT_SIZE; + LLVector3 u = gCamera->getUpAxis() * DOT_SIZE; + + LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; + LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; + LLVector3 topLeft = mSoundSymbol.mPosition + l + u; + LLVector3 topRight = mSoundSymbol.mPosition - l + u; + + //----------------------------- + // bind texture 0 (the dot) + //----------------------------- + mSoundSymbol.mTexture[0]->bind(); + + //------------------------------------------------------------- + // now render the dot + //------------------------------------------------------------- + glColor4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV ); + + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 0, 0 ); glVertex3fv( bottomLeft.mV ); + glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV ); + glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV ); + glEnd(); + + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV ); + glTexCoord2i( 1, 1 ); glVertex3fv( topRight.mV ); + glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV ); + glEnd(); + + + + //-------------------------------------------------------------------------------------- + // if currently speaking, trigger waves (1 through 6) based on speaking amplitude + //-------------------------------------------------------------------------------------- + if ( mCurrentlySpeaking ) + { + F32 min = 0.2f; + F32 max = 0.7f; + F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); + + // in case mSpeakingAmplitude > max.... + if ( fraction > 1.0f ) + { + fraction = 1.0f; + } + + S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); + + for (int i=0; i EXPANSION_MAX ) + { + mSoundSymbol.mWaveExpansion[i] = 1.0f; + } + + //---------------------------------------------------------------------------------- + // create geometry for the wave billboard textures + //---------------------------------------------------------------------------------- + F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i]; + F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; + + LLVector3 l = gCamera->getLeftAxis() * width; + LLVector3 u = gCamera->getUpAxis() * height; + + LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u; + LLVector3 bottomRight = mSoundSymbol.mPosition - l - u; + LLVector3 topLeft = mSoundSymbol.mPosition + l + u; + LLVector3 topRight = mSoundSymbol.mPosition - l + u; + + glColor4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV ); + mSoundSymbol.mTexture[i]->bind(); + + //--------------------------------------------------- + // now, render the mofo + //--------------------------------------------------- + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 0, 0 ); glVertex3fv( bottomLeft.mV ); + glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV ); + glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV ); + glEnd(); + + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV ); + glTexCoord2i( 1, 1 ); glVertex3fv( topRight.mV ); + glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV ); + glEnd(); + + } //if ( mSoundSymbol.mWaveActive[i] ) + + }// for loop + + }//if ( mSoundSymbol.mActive ) + +}//--------------------------------------------------- + + + + + +//--------------------------------------------------- +void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) +{ + mVoiceSourceWorldPosition = p; + +}//--------------------------------------------------- + +//--------------------------------------------------- +VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() +{ + VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default + + //----------------------------------------------------------------------------------------- + // Within the range of gesticulation amplitudes, the sound signal is split into + // three equal amplitude regimes, each specifying one of three gesticulation levels. + //----------------------------------------------------------------------------------------- + F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; + + if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.66666f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; } + else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.33333f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; } + else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; } + + return gesticulationLevel; + +}//--------------------------------------------------- + + + +//------------------------------------ +// Destructor +//------------------------------------ +LLVoiceVisualizer::~LLVoiceVisualizer() +{ +}//---------------------------------------------- + + +//--------------------------------------------------- +// "packData" is inherited from HUDEffect +//--------------------------------------------------- +void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) +{ + // Pack the default data + LLHUDEffect::packData(mesgsys); + + // TODO -- pack the relevant data for voice effects + // we'll come up with some cool configurations....TBD + //U8 packed_data[41]; + //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); + U8 packed_data = 0; + mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); +} + + +//--------------------------------------------------- +// "unpackData" is inherited from HUDEffect +//--------------------------------------------------- +void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) +{ + // TODO -- find the speaker, unpack binary data, set the properties of this effect + /* + LLHUDEffect::unpackData(mesgsys, blocknum); + LLUUID source_id; + LLUUID target_id; + S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); + if (size != 1) + { + llwarns << "Voice effect with bad size " << size << llendl; + return; + } + mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); + */ +} + + +//------------------------------------------------------------------ +// this method is inherited from HUD Effect +//------------------------------------------------------------------ +void LLVoiceVisualizer::markDead() +{ + mCurrentlySpeaking = false; + mVoiceEnabled = false; + mSoundSymbol.mActive = false; + +}//------------------------------------------------------------------ + + + + + + + + diff --git a/linden/indra/newview/llvoicevisualizer.h b/linden/indra/newview/llvoicevisualizer.h new file mode 100644 index 0000000..ea53372 --- /dev/null +++ b/linden/indra/newview/llvoicevisualizer.h @@ -0,0 +1,111 @@ +//-------------------------------------------------------------------- +// +// VOICE VISUALIZER +// author: JJ Ventrella, Linden Lab +// (latest update to this info: Jan 18, 2007) +// +// The Voice Visualizer is responsible for taking realtime signals from actual users speaking and +// visualizing this speech in two forms: +// +// (1) as a dynamic sound symbol (also referred to as the "voice indicator" that appears over the avatar's head +// (2) as gesticulation events that are used to trigger avatr gestures +// +// The input for the voice visualizer is a continual stream of voice amplitudes. + +//----------------------------------------------------------------------------- +#ifndef LL_VOICE_VISUALIZER_H +#define LL_VOICE_VISUALIZER_H + +#include "llhudeffect.h" + +//----------------------------------------------------------------------------------------------- +// The values of voice gesticulation represent energy levels for avatar animation, based on +// amplitude surge events parsed from the voice signal. These are made available so that +// the appropriate kind of avatar animation can be triggered, and thereby simulate the physical +// motion effects of speech. It is recommended that multiple body parts be animated as well as +// lips, such as head, shoulders, and hands, with large gestures used when the energy level is high. +//----------------------------------------------------------------------------------------------- +enum VoiceGesticulationLevel +{ + VOICE_GESTICULATION_LEVEL_OFF = -1, + VOICE_GESTICULATION_LEVEL_LOW = 0, + VOICE_GESTICULATION_LEVEL_MEDIUM, + VOICE_GESTICULATION_LEVEL_HIGH, + NUM_VOICE_GESTICULATION_LEVELS +}; + +const static int NUM_VOICE_SYMBOL_WAVES = 7; + +//---------------------------------------------------- +// LLVoiceVisualizer class +//---------------------------------------------------- +class LLVoiceVisualizer : public LLHUDEffect +{ + //--------------------------------------------------- + // public methods + //--------------------------------------------------- + public: + LLVoiceVisualizer ( const U8 type ); //constructor + ~LLVoiceVisualizer(); //destructor + + friend class LLHUDObject; + + void setVoiceSourceWorldPosition( const LLVector3 &p ); // this should be the position of the speaking avatar's head + void setMinGesticulationAmplitude( F32 ); // the lower range of meaningful amplitude for setting gesticulation level + void setMaxGesticulationAmplitude( F32 ); // the upper range of meaningful amplitude for setting gesticulation level + void setStartSpeaking(); // tell me when the av starts speaking + void setVoiceEnabled( bool ); // tell me whether or not the user is voice enabled + void setSpeakingAmplitude( F32 ); // tell me how loud the av is speaking (ranges from 0 to 1) + void setStopSpeaking(); // tell me when the av stops speaking + bool getCurrentlySpeaking(); // the get for the above set + VoiceGesticulationLevel getCurrentGesticulationLevel(); // based on voice amplitude, I'll give you the current "energy level" of avatar speech + + void render(); // inherited from HUD Effect + void packData(LLMessageSystem *mesgsys); // inherited from HUD Effect + void unpackData(LLMessageSystem *mesgsys, S32 blocknum); // inherited from HUD Effect + void markDead(); // inherited from HUD Effect + + //---------------------------------------------------------------------------------------------- + // "setMaxGesticulationAmplitude" and "setMinGesticulationAmplitude" allow for the tuning of the + // gesticulation level detector to be responsive to different kinds of signals. For instance, we + // may find that the average voice amplitude rarely exceeds 0.7 (in a range from 0 to 1), and + // therefore we may want to set 0.7 as the max, so we can more easily catch all the variance + // within that range. Also, we may find that there is often noise below a certain range like 0.1, + // and so we would want to set 0.1 as the min so as not to accidentally use this as signal. + //---------------------------------------------------------------------------------------------- + void setMaxGesticulationAmplitude(); + void setMinGesticulationAmplitude(); + + //--------------------------------------------------- + // private members + //--------------------------------------------------- + private: + + struct SoundSymbol + { + F32 mWaveExpansion [ NUM_VOICE_SYMBOL_WAVES ]; + bool mWaveActive [ NUM_VOICE_SYMBOL_WAVES ]; + F64 mWaveFadeOutStartTime [ NUM_VOICE_SYMBOL_WAVES ]; + F32 mWaveOpacity [ NUM_VOICE_SYMBOL_WAVES ]; + LLPointer mTexture [ NUM_VOICE_SYMBOL_WAVES ]; + bool mActive; + LLVector3 mPosition; + }; + + LLFrameTimer mTimer; // so I can ask the current time in seconds + F64 mCurrentTime; // current time in seconds, captured every step + F64 mPreviousTime; // copy of "current time" from last frame + SoundSymbol mSoundSymbol; // the sound symbol that appears over the avatar's head + bool mVoiceEnabled; // if off, no rendering should happen + bool mCurrentlySpeaking; // is the user currently speaking? + LLVector3 mVoiceSourceWorldPosition; // give this to me every step - I need it to update the sound symbol + F32 mSpeakingAmplitude; // this should be set as often as possible when the user is speaking + F32 mMaxGesticulationAmplitude; // this is the upper-limit of the envelope of detectable gesticulation leves + F32 mMinGesticulationAmplitude; // this is the lower-limit of the envelope of detectable gesticulation leves + +};//----------------------------------------------------------------- + // end of LLVoiceVisualizer class +//------------------------------------------------------------------ + +#endif //LL_VOICE_VISUALIZER_H + diff --git a/linden/indra/newview/llvolumesliderctrl.cpp b/linden/indra/newview/llvolumesliderctrl.cpp deleted file mode 100644 index 54cfa30..0000000 --- a/linden/indra/newview/llvolumesliderctrl.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @file llvolumesliderctrl.cpp - * @brief Horizontal volume slider. - * - * Copyright (c) 2004-2007, 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 - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#include "llviewerprecompiledheaders.h" - -#include "llvolumesliderctrl.h" - -#include "llfocusmgr.h" - -#include "llui.h" - -const F32 VOL_DEFAULT = 0.125f; -const F32 VOL_MIN = 0.f; -const F32 VOL_MAX = 0.5f; -const F32 VOL_INC = 0.01f; - -LLVolumeSliderCtrl::LLVolumeSliderCtrl(const std::string& name, - const LLRect& rect, - void (*commit_callback)(LLUICtrl*, void*), - void* callback_data) - : -LLSlider(name, rect, commit_callback, callback_data, - VOL_DEFAULT, - VOL_MIN, - VOL_MAX, - VOL_INC) -{ } - -LLVolumeSliderCtrl::~LLVolumeSliderCtrl() -{ } - -// virtual -void LLVolumeSliderCtrl::draw() -{ - if(!getVisible()) return; - - F32 opacity = mEnabled ? 1.f : 0.3f; - - // Track - LLRect track(0, mRect.getHeight(), mRect.getWidth(), 0); - - track.mBottom += 3; - track.mTop -= 1; - track.mRight -= 1; - - LLColor4 center_color = (mThumbCenterColor % opacity); - LLColor4 outline_color = (mThumbOutlineColor % opacity); - - gl_triangle_2d(track.mLeft, track.mBottom, - track.mRight, track.mBottom, - track.mRight, track.mTop, - center_color, - TRUE); - gl_triangle_2d(track.mLeft, track.mBottom, - track.mRight, track.mBottom, - track.mRight, track.mTop, - outline_color, - FALSE); - - if (hasMouseCapture()) - { - // Thumb - LLRect rect(mDragStartThumbRect); - gl_rect_2d( rect, outline_color ); - rect.stretch(-1); - gl_rect_2d( rect, mThumbCenterColor % 0.3f ); - - // Thumb - if (gFocusMgr.childHasKeyboardFocus(this)) - { - LLRect thumb_rect = mThumbRect; - thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt()))); - gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor()); - } - gl_rect_2d( mThumbRect, mThumbOutlineColor ); - } - else - { - LLRect rect(mThumbRect); - // Thumb - if (gFocusMgr.childHasKeyboardFocus(this)) - { - LLRect thumb_rect = mThumbRect; - thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt()))); - gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor()); - } - - // Thumb - gl_rect_2d(rect, outline_color); - rect.stretch(-1); - gl_rect_2d( rect, center_color); - } - - LLUICtrl::draw(); -} - -// virtual -LLXMLNodePtr LLVolumeSliderCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - LLString control_name = getControlName(); - if (!control_name.empty()) - { - node->createChild("control_name", TRUE)->setStringValue(control_name); - } - node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue()); - node->createChild("min_val", TRUE)->setFloatValue(getMinValue()); - node->createChild("max_val", TRUE)->setFloatValue(getMaxValue()); - node->createChild("increment", TRUE)->setFloatValue(getIncrement()); - - return node; -} - -LLView* LLVolumeSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ LLString name("volume_slider"); - - node->getAttributeString("name", name); - - LLString label; - node->getAttributeString("label", label); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - LLFontGL* font = LLView::selectFont(node); - - // HACK: Font might not be specified. - if (!font) - { - font = LLFontGL::sSansSerifSmall; - } - - S32 label_width = font->getWidth(label) + 8; - node->getAttributeS32("label_width", label_width); - - LLString control_name; - node->getAttributeString("control_name", control_name); - - BOOL show_text = TRUE; - node->getAttributeBOOL("show_text", show_text); - - BOOL can_edit_text = FALSE; - node->getAttributeBOOL("can_edit_text", can_edit_text); - - F32 initial_value = 0.f; - node->getAttributeF32("initial_val", initial_value); - - F32 min_value = 0.f; - node->getAttributeF32("min_val", min_value); - - F32 max_value = 1.f; - node->getAttributeF32("max_val", max_value); - - F32 increment = 0.1f; - node->getAttributeF32("increment", increment); - - U32 precision = 3; - node->getAttributeU32("decimal_digits", precision); - - - LLVolumeSliderCtrl* slider = new LLVolumeSliderCtrl(name,rect,NULL,NULL); - - slider->initFromXML(node, parent); - - return slider; -} - diff --git a/linden/indra/newview/llvolumesliderctrl.h b/linden/indra/newview/llvolumesliderctrl.h deleted file mode 100644 index 096ecc3..0000000 --- a/linden/indra/newview/llvolumesliderctrl.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file llvolumesliderctrl.h - * @brief A horizontal volume slider. - * - * Copyright (c) 2004-2007, 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 - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - */ - -#ifndef LL_LLVOLUMESLIDERCTRL_H -#define LL_LLVOLUMESLIDERCTRL_H - -#include "llslider.h" - - -class LLVolumeSliderCtrl -: public LLSlider -{ -public: - - virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_VOLUME_SLIDER; } - virtual LLString getWidgetTag() const { return LL_VOLUME_SLIDER_CTRL_TAG; } - - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - - LLVolumeSliderCtrl(const std::string& name, - const LLRect& rect, - void (*commit_callback)(LLUICtrl* ctrl, void* data), - void* callback_data); - virtual ~LLVolumeSliderCtrl(); - - virtual void draw(); -}; - - -#endif diff --git a/linden/indra/newview/llvopartgroup.cpp b/linden/indra/newview/llvopartgroup.cpp index 94027a3..791b4ab 100644 --- a/linden/indra/newview/llvopartgroup.cpp +++ b/linden/indra/newview/llvopartgroup.cpp @@ -435,7 +435,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co drawablep->updateFaceSize(j); LLFace* facep = drawablep->getFace(j); - if (!facep->hasGeometry()) + if ( !facep || !facep->hasGeometry()) { continue; } diff --git a/linden/indra/newview/llvosky.cpp b/linden/indra/newview/llvosky.cpp index 2d31bf4..442ef23 100644 --- a/linden/indra/newview/llvosky.cpp +++ b/linden/indra/newview/llvosky.cpp @@ -1406,17 +1406,17 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) const F32 camera_height = mCameraPosAgent.mV[2]; const F32 height_above_water = camera_height - water_height; - BOOL sun = FALSE; + BOOL sun_flag = FALSE; if (mSun.isVisible()) { if (mMoon.isVisible()) { - sun = look_at * mSun.getDirection() > 0; + sun_flag = look_at * mSun.getDirection() > 0; } else { - sun = TRUE; + sun_flag = TRUE; } } @@ -1427,7 +1427,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) #else BOOL render_ref = !(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= LLDrawPoolWater::SHADER_LEVEL_RIPPLE); #endif - if (sun) + if (sun_flag) { setDrawRefl(0); if (render_ref) diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 45a9e0a..a752fca 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp @@ -406,15 +406,13 @@ void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) void LLVOTree::updateTextures(LLAgent &agent) { - F32 texel_area_ratio = 1.f; - F32 cos_angle = 1.f; if (mTreeImagep) { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); } - mTreeImagep->addTextureStats(mPixelArea, texel_area_ratio, cos_angle); + mTreeImagep->addTextureStats(mPixelArea); } } diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index ccf0cba..a0a83f5 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -800,6 +800,8 @@ BOOL LLVOVolume::updateLOD() mLODChanged = TRUE; } + lod_changed |= LLViewerObject::updateLOD(); + return lod_changed; } @@ -1128,7 +1130,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) mSculptChanged = FALSE; mFaceMappingChanged = FALSE; - return TRUE; + return LLViewerObject::updateGeometry(drawable); } void LLVOVolume::updateFaceSize(S32 idx) diff --git a/linden/indra/newview/llweb.cpp b/linden/indra/newview/llweb.cpp index 910f0c4..d15d4c4 100644 --- a/linden/indra/newview/llweb.cpp +++ b/linden/indra/newview/llweb.cpp @@ -47,7 +47,9 @@ void LLWeb::loadURL(std::string url) void LLWeb::loadURLExternal(std::string url) { std::string escaped_url = escapeURL(url); +#if LL_LIBXUL_ENABLED spawn_web_browser(escaped_url.c_str()); +#endif } diff --git a/linden/indra/newview/llwebbrowserctrl.cpp b/linden/indra/newview/llwebbrowserctrl.cpp index bd671fa..26e5076 100644 --- a/linden/indra/newview/llwebbrowserctrl.cpp +++ b/linden/indra/newview/llwebbrowserctrl.cpp @@ -280,10 +280,10 @@ BOOL LLWebBrowserCtrl::handleUnicodeChar(llwchar uni_char, BOOL called_from_pare //////////////////////////////////////////////////////////////////////////////// // -void LLWebBrowserCtrl::onVisibilityChange ( BOOL curVisibilityIn ) +void LLWebBrowserCtrl::onVisibilityChange ( BOOL new_visibility ) { // set state of frequent updates automatically if visibility changes - if ( curVisibilityIn ) + if ( new_visibility ) { mFrequentUpdates = true; } diff --git a/linden/indra/newview/llworldmap.cpp b/linden/indra/newview/llworldmap.cpp index db7ac19..82e6b6e 100644 --- a/linden/indra/newview/llworldmap.cpp +++ b/linden/indra/newview/llworldmap.cpp @@ -245,20 +245,25 @@ LLSimInfo* LLWorldMap::simInfoFromName(const LLString& sim_name) return sim_info; } -LLString LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global) +bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, LLString & outSimName ) { + bool gotSimName = true; + U64 handle = to_region_handle(pos_global); sim_info_map_t::iterator it = mSimInfoMap.find(handle); if (it != mSimInfoMap.end()) { LLSimInfo* info = (*it).second; - return info->mName.c_str(); + outSimName = info->mName.c_str(); } else { - return "(unknown region)"; + gotSimName = false; + outSimName = "(unknown region)"; } + + return gotSimName; } void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) diff --git a/linden/indra/newview/llworldmap.h b/linden/indra/newview/llworldmap.h index c4af7d8..5aaff63 100644 --- a/linden/indra/newview/llworldmap.h +++ b/linden/indra/newview/llworldmap.h @@ -135,8 +135,8 @@ public: // Returns simulator information for named sim, or NULL if non-existent LLSimInfo* simInfoFromName(const LLString& sim_name); - // Returns simulator name - LLString simNameFromPosGlobal(const LLVector3d& pos_global); + // Gets simulator name for a global position, returns true if it was found + bool simNameFromPosGlobal(const LLVector3d& pos_global, LLString & outSimName ); // Sets the current layer void setCurrentLayer(S32 layer, bool request_layer = false); diff --git a/linden/indra/newview/llworldmapview.cpp b/linden/indra/newview/llworldmapview.cpp index 328af72..0c98305 100644 --- a/linden/indra/newview/llworldmapview.cpp +++ b/linden/indra/newview/llworldmapview.cpp @@ -312,8 +312,7 @@ void LLWorldMapView::draw() const S32 half_height = height / 2; LLVector3d camera_global = gAgent.getCameraPositionGlobal(); - LLGLEnable scissor_test(GL_SCISSOR_TEST); - LLUI::setScissorRegionLocal(LLRect(0, height, width, 0)); + LLLocalClipRect clip(getLocalRect()); { LLGLSNoTexture no_texture; diff --git a/linden/indra/newview/llxmlrpctransaction.cpp b/linden/indra/newview/llxmlrpctransaction.cpp index 887b69d..55074a4 100644 --- a/linden/indra/newview/llxmlrpctransaction.cpp +++ b/linden/indra/newview/llxmlrpctransaction.cpp @@ -240,6 +240,8 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) curl_easy_setopt(mCurl, CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str()); curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, (long) gVerifySSLCert); curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, gVerifySSLCert? 2L : 0L); + // Be a little impatient about establishing connections. + curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 40L); /* Setting the DNS cache timeout to -1 disables it completely. This might help with bug #503 */ diff --git a/linden/indra/newview/macview.xcodeproj/project.pbxproj b/linden/indra/newview/macview.xcodeproj/project.pbxproj index 08e64b4..669833e 100644 --- a/linden/indra/newview/macview.xcodeproj/project.pbxproj +++ b/linden/indra/newview/macview.xcodeproj/project.pbxproj @@ -27,6 +27,9 @@ 1A0201850B7A861200D5C589 /* llblowfishcipher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A02017E0B7A861200D5C589 /* llblowfishcipher.cpp */; }; 1A0201860B7A861200D5C589 /* llnullcipher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0201810B7A861200D5C589 /* llnullcipher.cpp */; }; 1A0201870B7A861200D5C589 /* llxorcipher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0201830B7A861200D5C589 /* llxorcipher.cpp */; }; + 1A0DA5130C3AC07800361F49 /* llviewerjointmesh_vec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DA5100C3AC07700361F49 /* llviewerjointmesh_vec.cpp */; }; + 1A0DA5140C3AC07800361F49 /* llviewerjointmesh_sse2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DA5110C3AC07700361F49 /* llviewerjointmesh_sse2.cpp */; }; + 1A0DA5150C3AC07800361F49 /* llviewerjointmesh_sse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DA5120C3AC07700361F49 /* llviewerjointmesh_sse.cpp */; }; 1A1C61620847AEE6005D7227 /* llvolumemgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1C615E0847AEE6005D7227 /* llvolumemgr.cpp */; }; 1A1C61630847AEE6005D7227 /* llvolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1C615F0847AEE6005D7227 /* llvolume.cpp */; }; 1A1C61760847B307005D7227 /* llvolumemessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1C61740847B307005D7227 /* llvolumemessage.cpp */; }; @@ -260,7 +263,6 @@ 5503BC2505446B20003D051F /* llfloatermap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AAD051F61DF00A80050 /* llfloatermap.cpp */; }; 5503BC2705446B20003D051F /* llregionposition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AAF051F61DF00A80050 /* llregionposition.cpp */; }; 5503BC2905446B20003D051F /* llasynchostbyname.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AB2051F61DF00A80050 /* llasynchostbyname.cpp */; }; - 5503BC2A05446B20003D051F /* llaudiostatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AB3051F61DF00A80050 /* llaudiostatus.cpp */; }; 5503BC2B05446B20003D051F /* llpanelavatar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AB4051F61DF00A80050 /* llpanelavatar.cpp */; }; 5503BC2C05446B20003D051F /* llpanelaudioprefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AB5051F61DF00A80050 /* llpanelaudioprefs.cpp */; }; 5503BC2D05446B20003D051F /* llfloaterbuy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F52AB6051F61DF00A80050 /* llfloaterbuy.cpp */; }; @@ -423,6 +425,7 @@ 61923D6C074AE3C0005E1F34 /* llstatemachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61923D25074AE3C0005E1F34 /* llstatemachine.cpp */; }; 61923D6E074AE3C0005E1F34 /* lltargetingmotion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61923D27074AE3C0005E1F34 /* lltargetingmotion.cpp */; }; 61923D70074AE3C0005E1F34 /* llvisualparam.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61923D29074AE3C0005E1F34 /* llvisualparam.cpp */; }; + 79256EA30C57D6A5000AAFA4 /* llfloatervoicewizard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79256EA10C57D6A4000AAFA4 /* llfloatervoicewizard.cpp */; }; 84401E2F0A13CC9A006720A5 /* llfloatergroupinvite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84401E2D0A13CC9A006720A5 /* llfloatergroupinvite.cpp */; }; 84401E320A13CCB2006720A5 /* llpanelgroupinvite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84401E300A13CCB2006720A5 /* llpanelgroupinvite.cpp */; }; 8833693F0C18AF33007F52DA /* llimagepng.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8833693B0C18AF33007F52DA /* llimagepng.cpp */; }; @@ -431,7 +434,6 @@ 88A95BCA0C14D92C0027E363 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 88A95BC90C14D92C0027E363 /* libresolv.dylib */; }; 88AA282C0C17720D0032DF53 /* libpng12.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 88AA282B0C17720D0032DF53 /* libpng12.a */; }; 9104C0CC0778AE0F001EC4F6 /* llpanelmsgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9104C0CB0778AE0F001EC4F6 /* llpanelmsgs.cpp */; }; - 910D255306484F1A0034E66F /* llvolumesliderctrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910D255206484F1A0034E66F /* llvolumesliderctrl.cpp */; }; 9117EAA20BF24A6100845BD2 /* llpacketack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9117EAA10BF24A6100845BD2 /* llpacketack.cpp */; }; 9118669B07F4FAF700E3D5BC /* llmediaremotectrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9118669907F4FAF700E3D5BC /* llmediaremotectrl.cpp */; }; 911CAD87075BE87B00CD1090 /* llinventoryview.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 911CAD86075BE87B00CD1090 /* llinventoryview.cpp */; }; @@ -496,9 +498,13 @@ 9928ACA5056D9353003865BE /* CrashReporter.nib in Resources */ = {isa = PBXBuildFile; fileRef = 9928ACA4056D9353003865BE /* CrashReporter.nib */; }; 9930A8E40B8FB10A00197ECA /* language.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9930A8E30B8FB10A00197ECA /* language.txt */; }; 99321B14081DD26000678159 /* llworkerthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99321B12081DD26000678159 /* llworkerthread.cpp */; }; + 99374E4E0B5C6059008DB4BE /* lliosocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99374E460B5C603E008DB4BE /* lliosocket.cpp */; }; + 993A3E050B546D47007A0790 /* llvoiceclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 993A3E040B546D47007A0790 /* llvoiceclient.cpp */; }; 994ADAE30A8016E600061DFB /* libllmozlib.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 994ADAE20A8016E500061DFB /* libllmozlib.dylib */; }; 9950AF460B3762A1007E36E0 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; 9950AF610B3763DF007E36E0 /* libfmodwrapper.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 9967E9090B37533F0087BD1B /* libfmodwrapper.dylib */; }; + 9956CAFD0B96679C00F58C6D /* llprefsvoice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9956CAFC0B96679C00F58C6D /* llprefsvoice.cpp */; }; + 996209690B864D0E00392531 /* SLVoiceAgent.app in Resources */ = {isa = PBXBuildFile; fileRef = 996209680B864D0E00392531 /* SLVoiceAgent.app */; }; 9967E9200B3754800087BD1B /* libfmodwrapper.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9967E9090B37533F0087BD1B /* libfmodwrapper.dylib */; }; 9967E98D0B375B0E0087BD1B /* fmodwrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9967E9520B37564D0087BD1B /* fmodwrapper.cpp */; }; 9967E9B30B375D9D0087BD1B /* libfmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FDE8765009BEA39600AF6316 /* libfmod.a */; }; @@ -511,6 +517,7 @@ 99BB5176099AC2A4004BF9F2 /* llconfirmationmanager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99BB5174099AC2A4004BF9F2 /* llconfirmationmanager.cpp */; }; 99C6BFAA0A1BBD4800419AE7 /* llfloaterhtmlfind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99C6BFA90A1BBD4800419AE7 /* llfloaterhtmlfind.cpp */; }; 99C7B320081F128400499A23 /* llvfsthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91A154F8081DC15E0089988C /* llvfsthread.cpp */; }; + 99C9FA670B6AD9BF00A1BBA6 /* SLVoice in Resources */ = {isa = PBXBuildFile; fileRef = 99C9FA660B6AD9BF00A1BBA6 /* SLVoice */; }; 99DB67DF07C161A500CF3185 /* llmediaimplquicktime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99DB67DB07C161A500CF3185 /* llmediaimplquicktime.cpp */; }; 99E4326D092D5996003AE728 /* llassettype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99E4326B092D5996003AE728 /* llassettype.cpp */; }; 99E4350C092D644F003AE728 /* llmortician.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99E4350B092D644F003AE728 /* llmortician.cpp */; }; @@ -518,6 +525,10 @@ 99E43514092D64CC003AE728 /* llmemoryview.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99E43513092D64CC003AE728 /* llmemoryview.cpp */; }; 99E43517092D64E6003AE728 /* llvoinventorylistener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99E43516092D64E6003AE728 /* llvoinventorylistener.cpp */; }; 99E4351A092D6535003AE728 /* llcommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99E43519092D6535003AE728 /* llcommon.cpp */; }; + 99E63DFF0BCADD2F000C1751 /* libalut.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 99E63DEF0BCADD14000C1751 /* libalut.dylib */; }; + 99E63E000BCADD2F000C1751 /* libopenal.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 99E63DF20BCADD14000C1751 /* libopenal.dylib */; }; + 99E63E010BCADD2F000C1751 /* libortp.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 99E63DF00BCADD14000C1751 /* libortp.dylib */; }; + 99E63E020BCADD2F000C1751 /* libvivoxsdk.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 99E63DF10BCADD14000C1751 /* libvivoxsdk.dylib */; }; 99E64039081F1CB80009003F /* llgl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99E64036081F1CB80009003F /* llgl.cpp */; }; 99EDDF5C05892E720031B20D /* llfloaterlandholdings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99EDDF5B05892E720031B20D /* llfloaterlandholdings.cpp */; }; 99EDE33705896DC10031B20D /* SecondLife.nib in Resources */ = {isa = PBXBuildFile; fileRef = 99EDE33605896DC10031B20D /* SecondLife.nib */; }; @@ -563,6 +574,7 @@ AA02B9BC0B0CE44D00F2996D /* lltexturefetch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA02B9BA0B0CE44D00F2996D /* lltexturefetch.cpp */; }; AA0E2A610A2FDAEE0066250A /* llcontrol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA0E2A5F0A2FDAEE0066250A /* llcontrol.cpp */; }; AA0E2A640A2FDB340066250A /* lltoolpipette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA0E2A620A2FDB340066250A /* lltoolpipette.cpp */; }; + AA1183500C1DF9C400FDE5BA /* llpanelaudiovolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA11834E0C1DF9C400FDE5BA /* llpanelaudiovolume.cpp */; }; AA348DFA0B0EAB31002C3015 /* llcurl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA348DF80B0EAB31002C3015 /* llcurl.cpp */; }; AAA1336B0A3F94D000419F7C /* lluistring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAA133690A3F94D000419F7C /* lluistring.cpp */; }; AAC121A50A93A8380080E8A9 /* llfloatersellland.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAC121A30A93A8380080E8A9 /* llfloatersellland.cpp */; }; @@ -584,7 +596,11 @@ D64594680B3B732200FAB68F /* llimagejpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61923DA2074AE4F2005E1F34 /* llimagejpeg.cpp */; }; D64594690B3B732300FAB68F /* llimagetga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 61923DA4074AE4F2005E1F34 /* llimagetga.cpp */; }; D651349D0B3C40870042C56E /* llqueuedthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF9D84F08B405630094E8E7 /* llqueuedthread.cpp */; }; + D6B766800BFE8E9B00DC8153 /* llfloaterchatterbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6B7667F0BFE8E9A00DC8153 /* llfloaterchatterbox.cpp */; }; D6F77CBC0B445C3B0040826D /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9985A1270AC1FE4E00579AFB /* AppKit.framework */; }; + D8CA570F0BAF74FC0093D6D4 /* llvoicevisualizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D8CA570E0BAF74FC0093D6D4 /* llvoicevisualizer.cpp */; }; + D8EAB8B60BE7B3D10067DBB3 /* llfloateractivespeakers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D8EAB8B40BE7B3D10067DBB3 /* llfloateractivespeakers.cpp */; }; + D8EAB8BA0BE7B4490067DBB3 /* llvoiceremotectrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D8EAB8B80BE7B4490067DBB3 /* llvoiceremotectrl.cpp */; }; DA4B141B0B978815003F64DE /* llhttpsender.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA4B14140B978815003F64DE /* llhttpsender.cpp */; }; DA4B141C0B978815003F64DE /* llsdmessagebuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA4B14170B978815003F64DE /* llsdmessagebuilder.cpp */; }; DA4B141D0B978815003F64DE /* llsdmessagereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA4B14190B978815003F64DE /* llsdmessagereader.cpp */; }; @@ -820,6 +836,9 @@ 1A0201820B7A861200D5C589 /* llnullcipher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llnullcipher.h; sourceTree = ""; }; 1A0201830B7A861200D5C589 /* llxorcipher.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llxorcipher.cpp; sourceTree = ""; }; 1A0201840B7A861200D5C589 /* llxorcipher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llxorcipher.h; sourceTree = ""; }; + 1A0DA5100C3AC07700361F49 /* llviewerjointmesh_vec.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llviewerjointmesh_vec.cpp; sourceTree = ""; }; + 1A0DA5110C3AC07700361F49 /* llviewerjointmesh_sse2.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llviewerjointmesh_sse2.cpp; sourceTree = ""; }; + 1A0DA5120C3AC07700361F49 /* llviewerjointmesh_sse.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llviewerjointmesh_sse.cpp; sourceTree = ""; }; 1A1C615E0847AEE6005D7227 /* llvolumemgr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvolumemgr.cpp; sourceTree = ""; }; 1A1C615F0847AEE6005D7227 /* llvolume.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvolume.cpp; sourceTree = ""; }; 1A1C61600847AEE6005D7227 /* llvolumemgr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvolumemgr.h; sourceTree = ""; }; @@ -1091,7 +1110,6 @@ 26F52AAD051F61DF00A80050 /* llfloatermap.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloatermap.cpp; sourceTree = SOURCE_ROOT; }; 26F52AAF051F61DF00A80050 /* llregionposition.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llregionposition.cpp; sourceTree = SOURCE_ROOT; }; 26F52AB2051F61DF00A80050 /* llasynchostbyname.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llasynchostbyname.cpp; sourceTree = SOURCE_ROOT; }; - 26F52AB3051F61DF00A80050 /* llaudiostatus.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llaudiostatus.cpp; sourceTree = SOURCE_ROOT; }; 26F52AB4051F61DF00A80050 /* llpanelavatar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llpanelavatar.cpp; sourceTree = SOURCE_ROOT; }; 26F52AB5051F61DF00A80050 /* llpanelaudioprefs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llpanelaudioprefs.cpp; sourceTree = SOURCE_ROOT; }; 26F52AB6051F61DF00A80050 /* llfloaterbuy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloaterbuy.cpp; sourceTree = SOURCE_ROOT; }; @@ -1271,7 +1289,6 @@ 619221B2074A9B58005E1F34 /* v4coloru.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = v4coloru.h; sourceTree = ""; }; 619221B3074A9B58005E1F34 /* v4math.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = v4math.cpp; sourceTree = ""; }; 619221B4074A9B58005E1F34 /* v4math.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = v4math.h; sourceTree = ""; }; - 619221B5074A9B58005E1F34 /* vmath.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = vmath.h; sourceTree = ""; }; 619221B6074A9B58005E1F34 /* xform.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = xform.cpp; sourceTree = ""; }; 619221B7074A9B58005E1F34 /* xform.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = xform.h; sourceTree = ""; }; 619221B9074A9B59005E1F34 /* llassetstorage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llassetstorage.cpp; sourceTree = ""; }; @@ -1292,7 +1309,6 @@ 619221D7074A9B59005E1F34 /* llinstantmessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llinstantmessage.h; sourceTree = ""; }; 619221D8074A9B59005E1F34 /* llinvite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llinvite.h; sourceTree = ""; }; 619221D9074A9B59005E1F34 /* llloginflags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llloginflags.h; sourceTree = ""; }; - 619221DA074A9B59005E1F34 /* lllsltransmit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lllsltransmit.h; sourceTree = ""; }; 619221DB074A9B59005E1F34 /* llmail.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llmail.cpp; sourceTree = ""; }; 619221DC074A9B59005E1F34 /* llmail.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llmail.h; sourceTree = ""; }; 619221DD074A9B59005E1F34 /* llnamevalue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llnamevalue.cpp; sourceTree = ""; }; @@ -1422,7 +1438,6 @@ 61923CE0074AE2CB005E1F34 /* listener_openal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = listener_openal.h; sourceTree = ""; }; 61923CE1074AE2CB005E1F34 /* llaudiodecodemgr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llaudiodecodemgr.cpp; sourceTree = ""; }; 61923CE2074AE2CB005E1F34 /* llaudiodecodemgr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llaudiodecodemgr.h; sourceTree = ""; }; - 61923CE3074AE2CB005E1F34 /* llaudiosource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llaudiosource.h; sourceTree = ""; }; 61923CE5074AE2CB005E1F34 /* vorbisdecode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = vorbisdecode.cpp; sourceTree = ""; }; 61923CE6074AE2CB005E1F34 /* vorbisdecode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = vorbisdecode.h; sourceTree = ""; }; 61923CE7074AE2CB005E1F34 /* vorbisencode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = vorbisencode.cpp; sourceTree = ""; }; @@ -1482,6 +1497,8 @@ 61923DA5074AE4F2005E1F34 /* llimagetga.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llimagetga.h; sourceTree = ""; }; 61923DA8074AE4F3005E1F34 /* llmapimagetype.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llmapimagetype.h; sourceTree = ""; }; 6192E764074A7CE9005E1F34 /* libllcommon.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libllcommon.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 79256EA10C57D6A4000AAFA4 /* llfloatervoicewizard.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloatervoicewizard.cpp; sourceTree = ""; }; + 79256EA20C57D6A4000AAFA4 /* llfloatervoicewizard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatervoicewizard.h; sourceTree = ""; }; 84401E2D0A13CC9A006720A5 /* llfloatergroupinvite.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloatergroupinvite.cpp; sourceTree = ""; }; 84401E2E0A13CC9A006720A5 /* llfloatergroupinvite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatergroupinvite.h; sourceTree = ""; }; 84401E300A13CCB2006720A5 /* llpanelgroupinvite.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llpanelgroupinvite.cpp; sourceTree = ""; }; @@ -1497,7 +1514,6 @@ 8B2ECFA00534C21A00A80059 /* llfirstuse.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfirstuse.cpp; sourceTree = ""; }; 9104C0CB0778AE0F001EC4F6 /* llpanelmsgs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llpanelmsgs.cpp; sourceTree = ""; }; 9104C0CD0778AE20001EC4F6 /* llpanelmsgs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelmsgs.h; sourceTree = ""; }; - 910D255206484F1A0034E66F /* llvolumesliderctrl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvolumesliderctrl.cpp; sourceTree = ""; }; 9117EAA10BF24A6100845BD2 /* llpacketack.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llpacketack.cpp; sourceTree = ""; }; 9118669907F4FAF700E3D5BC /* llmediaremotectrl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llmediaremotectrl.cpp; sourceTree = ""; }; 9118669A07F4FAF700E3D5BC /* llmediaremotectrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llmediaremotectrl.h; sourceTree = ""; }; @@ -1611,7 +1627,14 @@ 99321B11081DD26000678159 /* llworkerthread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llworkerthread.h; sourceTree = ""; }; 99321B12081DD26000678159 /* llworkerthread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llworkerthread.cpp; sourceTree = ""; }; 9932ED1F056C1F0900554101 /* crashreporter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = crashreporter.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 99374E450B5C603E008DB4BE /* lliosocket.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lliosocket.h; sourceTree = ""; }; + 99374E460B5C603E008DB4BE /* lliosocket.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = lliosocket.cpp; sourceTree = ""; }; + 993A3E030B546D47007A0790 /* llvoiceclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvoiceclient.h; sourceTree = ""; }; + 993A3E040B546D47007A0790 /* llvoiceclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvoiceclient.cpp; sourceTree = ""; }; 994ADAE20A8016E500061DFB /* libllmozlib.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libllmozlib.dylib; path = "../../libraries/universal-darwin/lib_release/libllmozlib.dylib"; sourceTree = SOURCE_ROOT; }; + 9956CAFB0B96679C00F58C6D /* llprefsvoice.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llprefsvoice.h; sourceTree = ""; }; + 9956CAFC0B96679C00F58C6D /* llprefsvoice.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 30; path = llprefsvoice.cpp; sourceTree = ""; }; + 996209680B864D0E00392531 /* SLVoiceAgent.app */ = {isa = PBXFileReference; lastKnownFileType = wrapper.application; name = SLVoiceAgent.app; path = "vivox-runtime/universal-darwin/SLVoiceAgent.app"; sourceTree = SOURCE_ROOT; }; 9967E9090B37533F0087BD1B /* libfmodwrapper.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libfmodwrapper.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 9967E9520B37564D0087BD1B /* fmodwrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fmodwrapper.cpp; sourceTree = ""; }; 997B4BD006015820001B0407 /* viewer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = viewer.h; sourceTree = SOURCE_ROOT; }; @@ -1715,7 +1738,6 @@ 997B4C5C06015821001B0407 /* llpreviewtexture.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreviewtexture.h; sourceTree = SOURCE_ROOT; }; 997B4C5D06015821001B0407 /* llpreviewsound.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreviewsound.h; sourceTree = SOURCE_ROOT; }; 997B4C5E06015821001B0407 /* llpreviewscript.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreviewscript.h; sourceTree = SOURCE_ROOT; }; - 997B4C5F06015821001B0407 /* llpreviewobject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreviewobject.h; sourceTree = SOURCE_ROOT; }; 997B4C6006015821001B0407 /* llpreviewnotecard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreviewnotecard.h; sourceTree = SOURCE_ROOT; }; 997B4C6106015821001B0407 /* llpreviewlandmark.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreviewlandmark.h; sourceTree = SOURCE_ROOT; }; 997B4C6206015821001B0407 /* llpreview.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpreview.h; sourceTree = SOURCE_ROOT; }; @@ -1728,7 +1750,6 @@ 997B4C6C06015821001B0407 /* llpanelobject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelobject.h; sourceTree = SOURCE_ROOT; }; 997B4C6D06015822001B0407 /* llpanelnetwork.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelnetwork.h; sourceTree = SOURCE_ROOT; }; 997B4C6F06015822001B0407 /* llpanelmorph.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelmorph.h; sourceTree = SOURCE_ROOT; }; - 997B4C7106015822001B0407 /* llpanelleaderboard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelleaderboard.h; sourceTree = SOURCE_ROOT; }; 997B4C7206015822001B0407 /* llpanelland.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelland.h; sourceTree = SOURCE_ROOT; }; 997B4C7306015822001B0407 /* llpanelinventory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelinventory.h; sourceTree = SOURCE_ROOT; }; 997B4C7406015822001B0407 /* llpanelinput.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelinput.h; sourceTree = SOURCE_ROOT; }; @@ -1739,7 +1760,6 @@ 997B4C7C06015822001B0407 /* llpaneldisplay.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldisplay.h; sourceTree = SOURCE_ROOT; }; 997B4C7D06015822001B0407 /* llpaneldirpopular.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirpopular.h; sourceTree = SOURCE_ROOT; }; 997B4C7E06015822001B0407 /* llpaneldirplaces.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirplaces.h; sourceTree = SOURCE_ROOT; }; - 997B4C7F06015822001B0407 /* llpaneldirpicks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirpicks.h; sourceTree = SOURCE_ROOT; }; 997B4C8006015822001B0407 /* llpaneldirpeople.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirpeople.h; sourceTree = SOURCE_ROOT; }; 997B4C8206015822001B0407 /* llpaneldirland.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirland.h; sourceTree = SOURCE_ROOT; }; 997B4C8306015822001B0407 /* llpaneldirgroups.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirgroups.h; sourceTree = SOURCE_ROOT; }; @@ -1747,7 +1767,6 @@ 997B4C8506015822001B0407 /* llpaneldirevents.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirevents.h; sourceTree = SOURCE_ROOT; }; 997B4C8606015822001B0407 /* llpaneldirbrowser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldirbrowser.h; sourceTree = SOURCE_ROOT; }; 997B4C8906015822001B0407 /* llpaneldebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpaneldebug.h; sourceTree = SOURCE_ROOT; }; - 997B4C8A06015822001B0407 /* llpanelcreate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelcreate.h; sourceTree = SOURCE_ROOT; }; 997B4C8B06015822001B0407 /* llpanelcontents.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelcontents.h; sourceTree = SOURCE_ROOT; }; 997B4C8D06015822001B0407 /* llpanelavatar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelavatar.h; sourceTree = SOURCE_ROOT; }; 997B4C8E06015822001B0407 /* llpanelaudioprefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelaudioprefs.h; sourceTree = SOURCE_ROOT; }; @@ -1804,7 +1823,6 @@ 997B4CD106015822001B0407 /* llfloaterlandholdings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloaterlandholdings.h; sourceTree = SOURCE_ROOT; }; 997B4CD206015822001B0407 /* llfloaterland.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloaterland.h; sourceTree = SOURCE_ROOT; }; 997B4CD406015822001B0407 /* llfloatergroups.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatergroups.h; sourceTree = SOURCE_ROOT; }; - 997B4CD506015822001B0407 /* llfloatergroupprofile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatergroupprofile.h; sourceTree = SOURCE_ROOT; }; 997B4CD606015822001B0407 /* llfloatergroupinfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatergroupinfo.h; sourceTree = SOURCE_ROOT; }; 997B4CD806015822001B0407 /* llfloatergodtools.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatergodtools.h; sourceTree = SOURCE_ROOT; }; 997B4CD906015822001B0407 /* llfloatergesture.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloatergesture.h; sourceTree = SOURCE_ROOT; }; @@ -1828,7 +1846,6 @@ 997B4CF206015822001B0407 /* llemote.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llemote.h; sourceTree = SOURCE_ROOT; }; 997B4CF406015822001B0407 /* lldriverparam.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldriverparam.h; sourceTree = SOURCE_ROOT; }; 997B4CF506015823001B0407 /* lldrawpoolwater.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawpoolwater.h; sourceTree = SOURCE_ROOT; }; - 997B4CF606015823001B0407 /* lldrawpooltreenew.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawpooltreenew.h; sourceTree = SOURCE_ROOT; }; 997B4CF706015823001B0407 /* lldrawpooltree.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawpooltree.h; sourceTree = SOURCE_ROOT; }; 997B4CF806015823001B0407 /* lldrawpoolterrain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawpoolterrain.h; sourceTree = SOURCE_ROOT; }; 997B4CFA06015823001B0407 /* lldrawpoolsky.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawpoolsky.h; sourceTree = SOURCE_ROOT; }; @@ -1840,7 +1857,6 @@ 997B4D0006015823001B0407 /* lldrawpool.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawpool.h; sourceTree = SOURCE_ROOT; }; 997B4D0106015823001B0407 /* lldrawable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldrawable.h; sourceTree = SOURCE_ROOT; }; 997B4D0306015823001B0407 /* lldebugview.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lldebugview.h; sourceTree = SOURCE_ROOT; }; - 997B4D0506015823001B0407 /* llconversation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llconversation.h; sourceTree = SOURCE_ROOT; }; 997B4D0606015823001B0407 /* llcontainerview.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llcontainerview.h; sourceTree = SOURCE_ROOT; }; 997B4D0706015823001B0407 /* llconsole.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llconsole.h; sourceTree = SOURCE_ROOT; }; 997B4D0806015823001B0407 /* llcompilequeue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llcompilequeue.h; sourceTree = SOURCE_ROOT; }; @@ -1856,8 +1872,6 @@ 997B4D1806015823001B0407 /* llbbox.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llbbox.h; sourceTree = SOURCE_ROOT; }; 997B4D1C06015823001B0407 /* llaudiostatus.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llaudiostatus.h; sourceTree = SOURCE_ROOT; }; 997B4D1E06015823001B0407 /* llappearance.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llappearance.h; sourceTree = SOURCE_ROOT; }; - 997B4D2006015823001B0407 /* llagparray.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 30; path = llagparray.inl; sourceTree = SOURCE_ROOT; }; - 997B4D2106015823001B0407 /* llagparray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llagparray.h; sourceTree = SOURCE_ROOT; }; 997B4D2206015823001B0407 /* llagentpilot.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llagentpilot.h; sourceTree = SOURCE_ROOT; }; 997B4D2306015823001B0407 /* llagent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llagent.h; sourceTree = SOURCE_ROOT; }; 997B4D2406015823001B0407 /* head.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = head.h; sourceTree = SOURCE_ROOT; }; @@ -1879,6 +1893,7 @@ 99BB5175099AC2A4004BF9F2 /* llconfirmationmanager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llconfirmationmanager.h; sourceTree = SOURCE_ROOT; }; 99C6BFA80A1BBD4800419AE7 /* llfloaterhtmlfind.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloaterhtmlfind.h; sourceTree = ""; }; 99C6BFA90A1BBD4800419AE7 /* llfloaterhtmlfind.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloaterhtmlfind.cpp; sourceTree = ""; }; + 99C9FA660B6AD9BF00A1BBA6 /* SLVoice */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = SLVoice; path = "vivox-runtime/universal-darwin/SLVoice"; sourceTree = SOURCE_ROOT; }; 99D5703305BDEFD7004DE704 /* AutoUpdater.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoUpdater.app; sourceTree = BUILT_PRODUCTS_DIR; }; 99D5703505BDEFD8004DE704 /* AutoUpdater-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "AutoUpdater-Info.plist"; sourceTree = SOURCE_ROOT; }; 99D8B25508735BFE002F8938 /* material_codes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = material_codes.h; sourceTree = ""; }; @@ -1896,6 +1911,10 @@ 99E43516092D64E6003AE728 /* llvoinventorylistener.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvoinventorylistener.cpp; sourceTree = SOURCE_ROOT; }; 99E43518092D6535003AE728 /* llcommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = llcommon.h; path = ../llcommon/llcommon.h; sourceTree = SOURCE_ROOT; }; 99E43519092D6535003AE728 /* llcommon.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = llcommon.cpp; path = ../llcommon/llcommon.cpp; sourceTree = SOURCE_ROOT; }; + 99E63DEF0BCADD14000C1751 /* libalut.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libalut.dylib; path = "vivox-runtime/universal-darwin/libalut.dylib"; sourceTree = SOURCE_ROOT; }; + 99E63DF00BCADD14000C1751 /* libortp.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libortp.dylib; path = "vivox-runtime/universal-darwin/libortp.dylib"; sourceTree = SOURCE_ROOT; }; + 99E63DF10BCADD14000C1751 /* libvivoxsdk.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvivoxsdk.dylib; path = "vivox-runtime/universal-darwin/libvivoxsdk.dylib"; sourceTree = SOURCE_ROOT; }; + 99E63DF20BCADD14000C1751 /* libopenal.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libopenal.dylib; path = "vivox-runtime/universal-darwin/libopenal.dylib"; sourceTree = SOURCE_ROOT; }; 99E64035081F1CB80009003F /* llglheaders.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llglheaders.h; sourceTree = ""; }; 99E64036081F1CB80009003F /* llgl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llgl.cpp; sourceTree = ""; }; 99E64037081F1CB80009003F /* llgl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llgl.h; sourceTree = ""; }; @@ -1969,6 +1988,8 @@ AA0E2A600A2FDAEE0066250A /* llcontrol.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llcontrol.h; sourceTree = ""; }; AA0E2A620A2FDB340066250A /* lltoolpipette.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = lltoolpipette.cpp; sourceTree = ""; }; AA0E2A630A2FDB340066250A /* lltoolpipette.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lltoolpipette.h; sourceTree = ""; }; + AA11834E0C1DF9C400FDE5BA /* llpanelaudiovolume.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llpanelaudiovolume.cpp; sourceTree = ""; }; + AA11834F0C1DF9C400FDE5BA /* llpanelaudiovolume.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llpanelaudiovolume.h; sourceTree = ""; }; AA348DF80B0EAB31002C3015 /* llcurl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llcurl.cpp; sourceTree = ""; }; AA348DF90B0EAB31002C3015 /* llcurl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llcurl.h; sourceTree = ""; }; AAA133690A3F94D000419F7C /* lluistring.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = lluistring.cpp; sourceTree = ""; }; @@ -1981,6 +2002,8 @@ AAEAAF260A8104D8005F0707 /* llscrollingpanellist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llscrollingpanellist.h; sourceTree = ""; }; AAF5FFD00B13F71900D28A84 /* lltexturecache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = lltexturecache.cpp; sourceTree = ""; }; AAF5FFD10B13F71900D28A84 /* lltexturecache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lltexturecache.h; sourceTree = ""; }; + AB058FE40B3B74AD003C59D8 /* llvoicevisualizer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvoicevisualizer.h; sourceTree = ""; }; + ABD8702D0B3C68630007C63B /* llvoavatar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvoavatar.h; sourceTree = ""; }; C16C084E0B4AE6C7009AD67F /* llfloaterinspect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloaterinspect.cpp; sourceTree = ""; }; C16C084F0B4AE6C7009AD67F /* llfloaterinspect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloaterinspect.h; sourceTree = ""; }; C1F5D0A30B138AEB00827F1D /* lluserrelations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = lluserrelations.cpp; sourceTree = ""; }; @@ -2001,6 +2024,14 @@ D62831620B4F3FA200F8830F /* llimagegl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llimagegl.h; sourceTree = ""; }; D62831640B4F3FA200F8830F /* llvertexprogramgl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvertexprogramgl.cpp; sourceTree = ""; }; D62831650B4F3FA200F8830F /* llvertexprogramgl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvertexprogramgl.h; sourceTree = ""; }; + D6B7667F0BFE8E9A00DC8153 /* llfloaterchatterbox.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloaterchatterbox.cpp; sourceTree = ""; }; + D6B766820BFE8ED700DC8153 /* llfloaterchatterbox.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloaterchatterbox.h; sourceTree = ""; }; + D8CA570D0BAF74FC0093D6D4 /* llvoicevisualizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = llvoicevisualizer.h; sourceTree = ""; }; + D8CA570E0BAF74FC0093D6D4 /* llvoicevisualizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = llvoicevisualizer.cpp; sourceTree = ""; }; + D8EAB8B40BE7B3D10067DBB3 /* llfloateractivespeakers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llfloateractivespeakers.cpp; sourceTree = ""; }; + D8EAB8B50BE7B3D10067DBB3 /* llfloateractivespeakers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llfloateractivespeakers.h; sourceTree = ""; }; + D8EAB8B80BE7B4490067DBB3 /* llvoiceremotectrl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvoiceremotectrl.cpp; sourceTree = ""; }; + D8EAB8B90BE7B4490067DBB3 /* llvoiceremotectrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvoiceremotectrl.h; sourceTree = ""; }; DA4B14140B978815003F64DE /* llhttpsender.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llhttpsender.cpp; sourceTree = ""; }; DA4B14150B978815003F64DE /* llhttpsender.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llhttpsender.h; sourceTree = ""; }; DA4B14160B978815003F64DE /* llmessagetemplate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llmessagetemplate.h; sourceTree = ""; }; @@ -2083,7 +2114,6 @@ EB3EE713083AC23D002BF676 /* llviewertexteditor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llviewertexteditor.h; sourceTree = ""; }; EB3EE714083AC23D002BF676 /* llvieweruictrlfactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvieweruictrlfactory.cpp; sourceTree = ""; }; EB3EE715083AC23D002BF676 /* llvieweruictrlfactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvieweruictrlfactory.h; sourceTree = ""; }; - EB3EE716083AC23D002BF676 /* llvolumesliderctrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llvolumesliderctrl.h; sourceTree = ""; }; EB3EE725083AC2F2002BF676 /* llimagedxt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llimagedxt.cpp; sourceTree = ""; }; EB3EE726083AC2F2002BF676 /* llimagedxt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = llimagedxt.h; sourceTree = ""; }; EB9E8314082AEEF2007B4479 /* llmenugl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llmenugl.cpp; sourceTree = ""; }; @@ -2327,7 +2357,13 @@ children = ( 019200F204DD7D3500A800A7 /* macview.r */, 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */, + 99C9FA660B6AD9BF00A1BBA6 /* SLVoice */, + 996209680B864D0E00392531 /* SLVoiceAgent.app */, 9930A8E30B8FB10A00197ECA /* language.txt */, + 99E63DEF0BCADD14000C1751 /* libalut.dylib */, + 99E63DF00BCADD14000C1751 /* libortp.dylib */, + 99E63DF10BCADD14000C1751 /* libvivoxsdk.dylib */, + 99E63DF20BCADD14000C1751 /* libopenal.dylib */, ); name = Resources; sourceTree = ""; @@ -2345,6 +2381,25 @@ 26F529A0051F61CD00A80050 /* newview */ = { isa = PBXGroup; children = ( + 79256EA10C57D6A4000AAFA4 /* llfloatervoicewizard.cpp */, + 79256EA20C57D6A4000AAFA4 /* llfloatervoicewizard.h */, + AA11834E0C1DF9C400FDE5BA /* llpanelaudiovolume.cpp */, + AA11834F0C1DF9C400FDE5BA /* llpanelaudiovolume.h */, + D6B766820BFE8ED700DC8153 /* llfloaterchatterbox.h */, + D6B7667F0BFE8E9A00DC8153 /* llfloaterchatterbox.cpp */, + D8EAB8B80BE7B4490067DBB3 /* llvoiceremotectrl.cpp */, + D8EAB8B90BE7B4490067DBB3 /* llvoiceremotectrl.h */, + D8EAB8B40BE7B3D10067DBB3 /* llfloateractivespeakers.cpp */, + D8EAB8B50BE7B3D10067DBB3 /* llfloateractivespeakers.h */, + 9956CAFB0B96679C00F58C6D /* llprefsvoice.h */, + 9956CAFC0B96679C00F58C6D /* llprefsvoice.cpp */, + 993A3E030B546D47007A0790 /* llvoiceclient.h */, + 993A3E040B546D47007A0790 /* llvoiceclient.cpp */, + ABD8702D0B3C68630007C63B /* llvoavatar.h */, + AB058FE40B3B74AD003C59D8 /* llvoicevisualizer.h */, + 1A0DA5100C3AC07700361F49 /* llviewerjointmesh_vec.cpp */, + 1A0DA5110C3AC07700361F49 /* llviewerjointmesh_sse2.cpp */, + 1A0DA5120C3AC07700361F49 /* llviewerjointmesh_sse.cpp */, 26F52A9D051F61DF00A80050 /* head.cpp */, 26F52A41051F61DF00A80050 /* llagent.cpp */, 1A758C910A436FCA00589675 /* llagentdata.cpp */, @@ -2353,7 +2408,6 @@ FD59ED5E0AF2AF460086642A /* llassetuploadresponders.h */, 26F52AB2051F61DF00A80050 /* llasynchostbyname.cpp */, 918166CA06516C59005727DC /* llaudiosourcevo.cpp */, - 26F52AB3051F61DF00A80050 /* llaudiostatus.cpp */, 26F52A33051F61DF00A80050 /* llbbox.cpp */, 26F52ABF051F61DF00A80050 /* llbox.cpp */, 26F529F0051F61DF00A80050 /* llcallbacklist.cpp */, @@ -2703,8 +2757,6 @@ 26F529CF051F61DF00A80050 /* llvoground.cpp */, 99E43516092D64E6003AE728 /* llvoinventorylistener.cpp */, 99E43515092D64E6003AE728 /* llvoinventorylistener.h */, - 910D255206484F1A0034E66F /* llvolumesliderctrl.cpp */, - EB3EE716083AC23D002BF676 /* llvolumesliderctrl.h */, 26F529CD051F61DF00A80050 /* llvopartgroup.cpp */, 26F529CC051F61DF00A80050 /* llvosky.cpp */, A3077C0509DCB8140059ED75 /* llvostars.cpp */, @@ -2730,6 +2782,8 @@ 26F529BD051F61DF00A80050 /* noise.cpp */, 26F529BA051F61DF00A80050 /* pipeline.cpp */, 26E79A760520BEC400A80050 /* viewer.cpp */, + D8CA570D0BAF74FC0093D6D4 /* llvoicevisualizer.h */, + D8CA570E0BAF74FC0093D6D4 /* llvoicevisualizer.cpp */, ); name = newview; sourceTree = ""; @@ -2960,7 +3014,6 @@ 619221B2074A9B58005E1F34 /* v4coloru.h */, 619221B3074A9B58005E1F34 /* v4math.cpp */, 619221B4074A9B58005E1F34 /* v4math.h */, - 619221B5074A9B58005E1F34 /* vmath.h */, 619221B6074A9B58005E1F34 /* xform.cpp */, 619221B7074A9B58005E1F34 /* xform.h */, ); @@ -2971,6 +3024,8 @@ 619221B8074A9B58005E1F34 /* llmessage */ = { isa = PBXGroup; children = ( + 99374E450B5C603E008DB4BE /* lliosocket.h */, + 99374E460B5C603E008DB4BE /* lliosocket.cpp */, 9117EAA10BF24A6100845BD2 /* llpacketack.cpp */, 9CC281000BE79746006D8BDC /* llmessagetemplateparser.h */, 9CC280FE0BE79737006D8BDC /* llmessagetemplateparser.cpp */, @@ -3053,7 +3108,6 @@ 619221D7074A9B59005E1F34 /* llinstantmessage.h */, 619221D8074A9B59005E1F34 /* llinvite.h */, 619221D9074A9B59005E1F34 /* llloginflags.h */, - 619221DA074A9B59005E1F34 /* lllsltransmit.h */, 619221DB074A9B59005E1F34 /* llmail.cpp */, 619221DC074A9B59005E1F34 /* llmail.h */, 619221DD074A9B59005E1F34 /* llnamevalue.cpp */, @@ -3394,7 +3448,6 @@ 61923CE0074AE2CB005E1F34 /* listener_openal.h */, 61923CE1074AE2CB005E1F34 /* llaudiodecodemgr.cpp */, 61923CE2074AE2CB005E1F34 /* llaudiodecodemgr.h */, - 61923CE3074AE2CB005E1F34 /* llaudiosource.h */, 61923CE5074AE2CB005E1F34 /* vorbisdecode.cpp */, 61923CE6074AE2CB005E1F34 /* vorbisdecode.h */, 61923CE7074AE2CB005E1F34 /* vorbisencode.cpp */, @@ -3525,8 +3578,6 @@ 997B4D2306015823001B0407 /* llagent.h */, 1A758C990A43700400589675 /* llagentdata.h */, 997B4D2206015823001B0407 /* llagentpilot.h */, - 997B4D2106015823001B0407 /* llagparray.h */, - 997B4D2006015823001B0407 /* llagparray.inl */, 997B4D1E06015823001B0407 /* llappearance.h */, 997B4D2506015823001B0407 /* llasynchostbyname.h */, 997B4D1C06015823001B0407 /* llaudiostatus.h */, @@ -3544,7 +3595,6 @@ 997B4D0806015823001B0407 /* llcompilequeue.h */, 997B4D0706015823001B0407 /* llconsole.h */, 997B4D0606015823001B0407 /* llcontainerview.h */, - 997B4D0506015823001B0407 /* llconversation.h */, 997B4CEF06015822001B0407 /* llcubemap.h */, 997B4CEE06015822001B0407 /* llcylinder.h */, 997B4D0306015823001B0407 /* lldebugview.h */, @@ -3558,7 +3608,6 @@ 997B4CFA06015823001B0407 /* lldrawpoolsky.h */, 997B4CF806015823001B0407 /* lldrawpoolterrain.h */, 997B4CF706015823001B0407 /* lldrawpooltree.h */, - 997B4CF606015823001B0407 /* lldrawpooltreenew.h */, 997B4CF506015823001B0407 /* lldrawpoolwater.h */, 997B4CF406015822001B0407 /* lldriverparam.h */, 997B4CF206015822001B0407 /* llemote.h */, @@ -3588,7 +3637,6 @@ 997B4CD806015822001B0407 /* llfloatergodtools.h */, 997B4CD606015822001B0407 /* llfloatergroupinfo.h */, 84401E2E0A13CC9A006720A5 /* llfloatergroupinvite.h */, - 997B4CD506015822001B0407 /* llfloatergroupprofile.h */, 997B4CD406015822001B0407 /* llfloatergroups.h */, 997B4CD206015822001B0407 /* llfloaterland.h */, 997B4CD106015822001B0407 /* llfloaterlandholdings.h */, @@ -3656,7 +3704,6 @@ 997B4C8D06015822001B0407 /* llpanelavatar.h */, 99FBB048087363B00048A5CC /* llpanelclassified.h */, 997B4C8B06015822001B0407 /* llpanelcontents.h */, - 997B4C8A06015822001B0407 /* llpanelcreate.h */, 997B4C8906015822001B0407 /* llpaneldebug.h */, 997B4C8606015822001B0407 /* llpaneldirbrowser.h */, 99FBB090087366930048A5CC /* llpaneldirclassified.h */, @@ -3665,7 +3712,6 @@ 997B4C8306015822001B0407 /* llpaneldirgroups.h */, 997B4C8206015822001B0407 /* llpaneldirland.h */, 997B4C8006015822001B0407 /* llpaneldirpeople.h */, - 997B4C7F06015822001B0407 /* llpaneldirpicks.h */, 997B4C7E06015822001B0407 /* llpaneldirplaces.h */, 997B4C7D06015822001B0407 /* llpaneldirpopular.h */, 997B4C7C06015822001B0407 /* llpaneldisplay.h */, @@ -3684,7 +3730,6 @@ 997B4C7206015822001B0407 /* llpanelland.h */, 1A758C970A436FF000589675 /* llpanellandobjects.h */, 1A758C980A436FF400589675 /* llpanellandoptions.h */, - 997B4C7106015822001B0407 /* llpanelleaderboard.h */, A3AF6BD00A544F0A005B5E2C /* llpanellogin.h */, 997B4C6F06015822001B0407 /* llpanelmorph.h */, 9104C0CD0778AE20001EC4F6 /* llpanelmsgs.h */, @@ -3702,7 +3747,6 @@ 91FC1D4606527FEC009CF498 /* llpreviewgesture.h */, 997B4C6106015821001B0407 /* llpreviewlandmark.h */, 997B4C6006015821001B0407 /* llpreviewnotecard.h */, - 997B4C5F06015821001B0407 /* llpreviewobject.h */, 997B4C5E06015821001B0407 /* llpreviewscript.h */, 997B4C5D06015821001B0407 /* llpreviewsound.h */, 997B4C5C06015821001B0407 /* llpreviewtexture.h */, @@ -4052,6 +4096,12 @@ 99EDE33705896DC10031B20D /* SecondLife.nib in Resources */, FD53B3C309BDD5F900BFE3BC /* AutoUpdater.app in Resources */, FD53B3C409BDD5FA00BFE3BC /* crashreporter.app in Resources */, + 99C9FA670B6AD9BF00A1BBA6 /* SLVoice in Resources */, + 99E63DFF0BCADD2F000C1751 /* libalut.dylib in Resources */, + 99E63E000BCADD2F000C1751 /* libopenal.dylib in Resources */, + 99E63E010BCADD2F000C1751 /* libortp.dylib in Resources */, + 99E63E020BCADD2F000C1751 /* libvivoxsdk.dylib in Resources */, + 996209690B864D0E00392531 /* SLVoiceAgent.app in Resources */, 9930A8E40B8FB10A00197ECA /* language.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4302,7 +4352,6 @@ 5503BC2505446B20003D051F /* llfloatermap.cpp in Sources */, 5503BC2705446B20003D051F /* llregionposition.cpp in Sources */, 5503BC2905446B20003D051F /* llasynchostbyname.cpp in Sources */, - 5503BC2A05446B20003D051F /* llaudiostatus.cpp in Sources */, 5503BC2B05446B20003D051F /* llpanelavatar.cpp in Sources */, 5503BC2C05446B20003D051F /* llpanelaudioprefs.cpp in Sources */, 5503BC2D05446B20003D051F /* llfloaterbuy.cpp in Sources */, @@ -4349,7 +4398,6 @@ 91F8BBAC062DF91A00DE42BA /* llgesturemgr.cpp in Sources */, 91B9EB8306370586007B3F3E /* lldynamictexture.cpp in Sources */, 91B9EC4D06370E4E007B3F3E /* llfloaterimagepreview.cpp in Sources */, - 910D255306484F1A0034E66F /* llvolumesliderctrl.cpp in Sources */, 916083930649560B00CAF63E /* llfloateranimpreview.cpp in Sources */, 918166CC06516C59005727DC /* llaudiosourcevo.cpp in Sources */, 91FC1C8806527F19009CF498 /* llpreviewanim.cpp in Sources */, @@ -4534,6 +4582,7 @@ 1AEF0A5B0B2DFE72003F107C /* llrootview.cpp in Sources */, A30273570B3A13D800704420 /* llvertexbuffer.cpp in Sources */, 1A1F130C0B3919F100845A6C /* lleditmenuhandler.cpp in Sources */, + 993A3E050B546D47007A0790 /* llvoiceclient.cpp in Sources */, C16C08500B4AE6C7009AD67F /* llfloaterinspect.cpp in Sources */, A32748C10B5F38A80099BE18 /* llfont.cpp in Sources */, A32748BF0B5F38A00099BE18 /* llfontgl.cpp in Sources */, @@ -4542,6 +4591,8 @@ 1A0201850B7A861200D5C589 /* llblowfishcipher.cpp in Sources */, 1A0201860B7A861200D5C589 /* llnullcipher.cpp in Sources */, 1A0201870B7A861200D5C589 /* llxorcipher.cpp in Sources */, + 9956CAFD0B96679C00F58C6D /* llprefsvoice.cpp in Sources */, + D8CA570F0BAF74FC0093D6D4 /* llvoicevisualizer.cpp in Sources */, 1A83767E0BA2169600F28979 /* llviewergenericmessage.cpp in Sources */, 38D0FA6C0B4BF898003323BA /* lltemplatemessagebuilder.cpp in Sources */, 38D0FA6D0B4BF898003323BA /* llmessagetemplate.cpp in Sources */, @@ -4555,12 +4606,20 @@ 9C659A870BAB0B6E00D2EB60 /* llmessageconfig.cpp in Sources */, A3C20E4A0BB0BCDF007E872B /* llglslshader.cpp in Sources */, A3C20E4C0BB0BD12007E872B /* llviewerjoystick.cpp in Sources */, + D8EAB8B60BE7B3D10067DBB3 /* llfloateractivespeakers.cpp in Sources */, + D8EAB8BA0BE7B4490067DBB3 /* llvoiceremotectrl.cpp in Sources */, 1A8870D50BCC5A6300E89AA6 /* llinventorytype.cpp in Sources */, 1A8870E50BCC5A9500E89AA6 /* llviewermenufile.cpp in Sources */, + D6B766800BFE8E9B00DC8153 /* llfloaterchatterbox.cpp in Sources */, + AA1183500C1DF9C400FDE5BA /* llpanelaudiovolume.cpp in Sources */, 9CC280FF0BE79737006D8BDC /* llmessagetemplateparser.cpp in Sources */, 88A95BB20C14D5FC0027E363 /* llsrv.cpp in Sources */, 8833693F0C18AF33007F52DA /* llimagepng.cpp in Sources */, 883369400C18AF33007F52DA /* llpngwrapper.cpp in Sources */, + 1A0DA5130C3AC07800361F49 /* llviewerjointmesh_vec.cpp in Sources */, + 1A0DA5140C3AC07800361F49 /* llviewerjointmesh_sse2.cpp in Sources */, + 1A0DA5150C3AC07800361F49 /* llviewerjointmesh_sse.cpp in Sources */, + 79256EA30C57D6A5000AAFA4 /* llfloatervoicewizard.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4731,6 +4790,7 @@ D64594690B3B732300FAB68F /* llimagetga.cpp in Sources */, D651349D0B3C40870042C56E /* llqueuedthread.cpp in Sources */, 91469E7B0B4486C10009E8F9 /* llmime.cpp in Sources */, + 99374E4E0B5C6059008DB4BE /* lliosocket.cpp in Sources */, 913B26990B4DDCDA0030C3EC /* lllandmark.cpp in Sources */, DA9C40E00B54B4BA00DD6F44 /* llformat.cpp in Sources */, DA9C41140B54B8CA00DD6F44 /* lllivefile.cpp in Sources */, @@ -4846,6 +4906,7 @@ 9919347D09786FF300BF6EE0 /* Universal */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = llcommon; }; name = Universal; @@ -4856,13 +4917,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = macutil_Prefix.h; INFOPLIST_FILE = "AutoUpdater-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = AutoUpdater; }; name = Universal; @@ -4873,13 +4928,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = macutil_Prefix.h; INFOPLIST_FILE = "crashreporter-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = crashreporter; }; name = Universal; @@ -4895,9 +4944,9 @@ INFOPLIST_FILE = "Info-SecondLife.plist"; INSTALL_PATH = Applications; LIBRARY_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)", - "$(LIBRARY_SEARCH_PATHS)", + "$(inherited)", "$(SRCROOT)/../../libraries/universal-darwin/lib_release", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", ); PRODUCT_NAME = "Second Life"; SEPARATE_STRIP = YES; @@ -4914,11 +4963,12 @@ i386, ppc, ); + DEBUG_INFORMATION_FORMAT = dwarf; GCC_ALTIVEC_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = 3; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = NO; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; @@ -4941,6 +4991,7 @@ ../../libraries/include, ../llcommon, ); + LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; MACOSX_DEPLOYMENT_TARGET_ppc = 10.3; OTHER_CFLAGS = ( @@ -4963,6 +5014,7 @@ "-Wno-sign-compare", "-Wno-switch", ); + ZERO_LINK = NO; }; name = Universal; }; @@ -4980,7 +5032,7 @@ GENERATE_MASTER_OBJECT_FILE = NO; INSTALL_PATH = "@executable_path/../Resources/"; KEEP_PRIVATE_EXTERNS = NO; - LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PREBINDING = NO; PRELINK_LIBS = ""; PRODUCT_NAME = fmodwrapper; @@ -5001,7 +5053,7 @@ GENERATE_MASTER_OBJECT_FILE = NO; INSTALL_PATH = "@executable_path/../Resources/"; KEEP_PRIVATE_EXTERNS = NO; - LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PREBINDING = NO; PRELINK_LIBS = ""; PRODUCT_NAME = fmodwrapper; @@ -5020,7 +5072,7 @@ GENERATE_MASTER_OBJECT_FILE = NO; INSTALL_PATH = "@executable_path/../Resources/"; KEEP_PRIVATE_EXTERNS = NO; - LIBRARY_SEARCH_PATHS = ""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = ""; PREBINDING = NO; PRELINK_LIBS = ""; @@ -5033,6 +5085,7 @@ 9994843B0883114200EFC621 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = llcommon; }; name = Development; @@ -5040,6 +5093,7 @@ 9994843C0883114200EFC621 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = llcommon; }; name = Deployment; @@ -5050,13 +5104,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = macutil_Prefix.h; INFOPLIST_FILE = "crashreporter-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = crashreporter; }; name = Development; @@ -5067,13 +5115,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = macutil_Prefix.h; INFOPLIST_FILE = "crashreporter-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = crashreporter; }; name = Deployment; @@ -5084,13 +5126,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = macutil_Prefix.h; INFOPLIST_FILE = "AutoUpdater-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = AutoUpdater; }; name = Development; @@ -5101,13 +5137,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = macutil_Prefix.h; INFOPLIST_FILE = "AutoUpdater-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = AutoUpdater; }; name = Deployment; @@ -5123,14 +5153,11 @@ INFOPLIST_FILE = "Info-SecondLife.plist"; INSTALL_PATH = "$(HOME)/Applications"; LIBRARY_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)", - "$(LIBRARY_SEARCH_PATHS)", + "$(inherited)", "$(SRCROOT)/../../libraries/universal-darwin/lib_release", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/vivox-runtime/universal-darwin\""; OTHER_LDFLAGS = "-weak-lllmozlib"; PRODUCT_NAME = "Second Life"; SHARED_PRECOMPS_DIR = "$(BUILD_DIR)/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders"; @@ -5155,13 +5182,11 @@ INFOPLIST_FILE = "Info-SecondLife.plist"; INSTALL_PATH = "$(HOME)/Applications"; LIBRARY_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)", - "$(LIBRARY_SEARCH_PATHS)", + "$(inherited)", "$(SRCROOT)/../../libraries/universal-darwin/lib_release", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/vivox-runtime/universal-darwin\""; LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; OTHER_LDFLAGS = "-lllmozlib"; PRODUCT_NAME = "Second Life"; @@ -5174,11 +5199,12 @@ 999484590883114300EFC621 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; GCC_ALTIVEC_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = NO; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; @@ -5201,6 +5227,7 @@ ../../libraries/include, ../llcommon, ); + LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; MACOSX_DEPLOYMENT_TARGET_ppc = 10.3; OTHER_CFLAGS = ( @@ -5222,17 +5249,19 @@ "-Wno-sign-compare", "-Wno-switch", ); + ZERO_LINK = YES; }; name = Development; }; 9994845A0883114300EFC621 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; GCC_ALTIVEC_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = 3; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = NO; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; @@ -5255,6 +5284,7 @@ ../../libraries/include, ../llcommon, ); + LIBRARY_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; MACOSX_DEPLOYMENT_TARGET_ppc = 10.3; OTHER_CFLAGS = ( @@ -5277,6 +5307,7 @@ "-Wno-sign-compare", "-Wno-switch", ); + ZERO_LINK = NO; }; name = Deployment; }; @@ -5291,13 +5322,7 @@ GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = "@executable_path/../Resources/"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); - LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Development\""; - LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../libraries/powerpc-darwin/lib_debug\""; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PREBINDING = NO; PRODUCT_NAME = llkdu; ZERO_LINK = YES; @@ -5313,11 +5338,7 @@ GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = "@executable_path/../Resources/"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", - "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", - ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Deployment\""; LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../libraries/powerpc-darwin/lib_release\""; PREBINDING = NO; @@ -5333,12 +5354,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; INSTALL_PATH = "@executable_path/../Resources/"; - LIBRARY_SEARCH_PATHS = ( - "$(BUILT_PRODUCTS_DIR)", - "$(inherited)", - "$(SRCROOT)/../../libraries/i386-darwin/lib_release", - "$(SRCROOT)/../../libraries/powerpc-darwin/lib_release", - ); + LIBRARY_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Deployment"; LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../../libraries/powerpc-darwin/lib_release\""; PREBINDING = NO; diff --git a/linden/indra/newview/moviemaker.cpp b/linden/indra/newview/moviemaker.cpp index 6a7da3f..34e5a16 100644 --- a/linden/indra/newview/moviemaker.cpp +++ b/linden/indra/newview/moviemaker.cpp @@ -36,6 +36,7 @@ #include #include #include +#include "llmemtype.h" #if LL_WINDOWS @@ -515,8 +516,9 @@ OSStatus MovieMaker::setupMovie() rowBytes = width * 4; bufferSize = height * rowBytes; - buffer = (char*)malloc(bufferSize); - invertedBuffer = (char*)malloc(bufferSize); + LLMemType mt(LLMemType::MTYPE_SCRIPT); + buffer = (char*) new char(bufferSize); + invertedBuffer = (char*) new char(bufferSize); rect.left = 0; rect.top = 0; @@ -684,13 +686,13 @@ void MovieMaker::EndCapture() if(buffer) { - free(buffer); + delete(buffer); buffer = NULL; } if(invertedBuffer) { - free(invertedBuffer); + delete(invertedBuffer); invertedBuffer = NULL; } } diff --git a/linden/indra/newview/newview.vcproj b/linden/indra/newview/newview.vcproj index 955d71a..199083f 100644 --- a/linden/indra/newview/newview.vcproj +++ b/linden/indra/newview/newview.vcproj @@ -224,7 +224,7 @@ Name="VCCustomBuildTool"/> + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RelativePath=".\llvoiceclient.cpp"> + RelativePath=".\llvoiceremotectrl.cpp"> + + + + @@ -1275,6 +1361,9 @@ RelativePath=".\audiosettings.h"> + + + RelativePath=".\llassetuploadresponders.h"> + RelativePath=".\llasynchostbyname.h"> + RelativePath=".\llaudiosourcevo.h"> @@ -1455,6 +1544,9 @@ RelativePath=".\llfloaterabout.h"> + + + + + + + + + RelativePath=".\llvoiceclient.h"> + + + RelativePath=".\llvoicevisualizer.h"> + + @@ -2339,12 +2446,18 @@ RelativePath=".\skins\xui\en-us\floater_account_history.xml"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2901,7 +3077,8 @@ diff --git a/linden/indra/newview/newview_vc8.vcproj b/linden/indra/newview/newview_vc8.vcproj index 032a6bf..ba05819 100644 --- a/linden/indra/newview/newview_vc8.vcproj +++ b/linden/indra/newview/newview_vc8.vcproj @@ -428,10 +428,6 @@ > - - @@ -632,6 +628,10 @@ > + + @@ -680,6 +680,10 @@ > + + @@ -836,6 +840,10 @@ > + + @@ -1056,6 +1064,10 @@ > + + @@ -1232,6 +1244,10 @@ > + + @@ -1512,6 +1528,98 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1628,11 +1736,19 @@ > + + + + - - @@ -1974,6 +2086,10 @@ > + + @@ -2022,6 +2138,10 @@ > + + @@ -2178,6 +2298,10 @@ > + + @@ -2390,6 +2514,10 @@ > + + @@ -2574,6 +2702,10 @@ > + + @@ -2986,11 +3118,19 @@ > + + + + + + + + + + + + + + + + + + getParent() && vobj->flagScripted()) { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) + { + gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + } + } + } +} + +void renderScriptedTouchBeacons(LLDrawable* drawablep) +{ + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + && !vobj->getParent() + && vobj->flagScripted() + && vobj->flagHandleTouch()) + { + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) + { + gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + } + } } } @@ -1501,7 +1550,19 @@ void renderPhysicalBeacons(LLDrawable* drawablep) && !vobj->getParent() && vobj->usePhysics()) { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) + { + gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + } + } } } @@ -1512,20 +1573,13 @@ void renderParticleBeacons(LLDrawable* drawablep) if (vobj && vobj->isParticleSource()) { - LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); - } -} + if (gPipeline.sRenderBeacons) + { + LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + } -void LLPipeline::highlightPhysical(LLDrawable* drawablep) -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - LLViewerObject *vobj; - vobj = drawablep->getVObj(); - if (vobj && !vobj->isAvatar()) - { - if (!vobj->isAvatar() && - (vobj->usePhysics() || vobj->flagHandleTouch())) + if (gPipeline.sRenderHighlight) { S32 face_id; for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) @@ -1699,42 +1753,49 @@ void LLPipeline::postSort(LLCamera& camera) std::sort(mAlphaGroups.begin(), mAlphaGroups.end(), LLSpatialGroup::CompareDepthGreater()); std::sort(mAlphaGroupsPostWater.begin(), mAlphaGroupsPostWater.end(), LLSpatialGroup::CompareDepthGreater()); - if (sRenderScriptedBeacons) + // only render if the flag is set. The flag is only set if the right key is pressed, we are in edit mode or the toggle is set in the menus + if (sRenderProcessBeacons) { - // Only show the beacon on the root object. - forAllVisibleDrawables(renderScriptedBeacons); - } - - if (sRenderPhysicalBeacons) - { - // Only show the beacon on the root object. - forAllVisibleDrawables(renderPhysicalBeacons); - } + if (sRenderScriptedTouchBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderScriptedTouchBeacons); + } + else + if (sRenderScriptedBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderScriptedBeacons); + } - if (sRenderParticleBeacons) - { - forAllVisibleDrawables(renderParticleBeacons); - } + if (sRenderPhysicalBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderPhysicalBeacons); + } - // Draw physical objects in red. - if (gHUDManager->getShowPhysical()) - { - forAllVisibleDrawables(highlightPhysical); - } + if (sRenderParticleBeacons) + { + forAllVisibleDrawables(renderParticleBeacons); + } - // If god mode, also show audio cues - if (sRenderSoundBeacons && gAudiop) - { - // Update all of our audio sources, clean up dead ones. - LLAudioEngine::source_map::iterator iter; - for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter) + // If god mode, also show audio cues + if (sRenderSoundBeacons && gAudiop) { - LLAudioSource *sourcep = iter->second; + // Update all of our audio sources, clean up dead ones. + LLAudioEngine::source_map::iterator iter; + for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter) + { + LLAudioSource *sourcep = iter->second; - LLVector3d pos_global = sourcep->getPositionGlobal(); - LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global); - //pos += LLVector3(0.f, 0.f, 0.2f); - gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + LLVector3d pos_global = sourcep->getPositionGlobal(); + LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global); + if (gPipeline.sRenderBeacons) + { + //pos += LLVector3(0.f, 0.f, 0.2f); + gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + } + } } } @@ -3448,6 +3509,12 @@ BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data) } // static +void LLPipeline::setRenderScriptedBeacons(BOOL val) +{ + sRenderScriptedBeacons = val; +} + +// static void LLPipeline::toggleRenderScriptedBeacons(void*) { sRenderScriptedBeacons = !sRenderScriptedBeacons; @@ -3460,6 +3527,30 @@ BOOL LLPipeline::getRenderScriptedBeacons(void*) } // static +void LLPipeline::setRenderScriptedTouchBeacons(BOOL val) +{ + sRenderScriptedTouchBeacons = val; +} + +// static +void LLPipeline::toggleRenderScriptedTouchBeacons(void*) +{ + sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons; +} + +// static +BOOL LLPipeline::getRenderScriptedTouchBeacons(void*) +{ + return sRenderScriptedTouchBeacons; +} + +// static +void LLPipeline::setRenderPhysicalBeacons(BOOL val) +{ + sRenderPhysicalBeacons = val; +} + +// static void LLPipeline::toggleRenderPhysicalBeacons(void*) { sRenderPhysicalBeacons = !sRenderPhysicalBeacons; @@ -3472,6 +3563,12 @@ BOOL LLPipeline::getRenderPhysicalBeacons(void*) } // static +void LLPipeline::setRenderParticleBeacons(BOOL val) +{ + sRenderParticleBeacons = val; +} + +// static void LLPipeline::toggleRenderParticleBeacons(void*) { sRenderParticleBeacons = !sRenderParticleBeacons; @@ -3484,6 +3581,12 @@ BOOL LLPipeline::getRenderParticleBeacons(void*) } // static +void LLPipeline::setRenderSoundBeacons(BOOL val) +{ + sRenderSoundBeacons = val; +} + +// static void LLPipeline::toggleRenderSoundBeacons(void*) { sRenderSoundBeacons = !sRenderSoundBeacons; @@ -3495,6 +3598,48 @@ BOOL LLPipeline::getRenderSoundBeacons(void*) return sRenderSoundBeacons; } +// static +void LLPipeline::setRenderBeacons(BOOL val) +{ + sRenderBeacons = val; +} + +// static +void LLPipeline::toggleRenderBeacons(void*) +{ + sRenderBeacons = !sRenderBeacons; +} + +// static +BOOL LLPipeline::getRenderBeacons(void*) +{ + return sRenderBeacons; +} + +// static +void LLPipeline::setRenderHighlights(BOOL val) +{ + sRenderHighlight = val; +} + +// static +void LLPipeline::toggleRenderHighlights(void*) +{ + sRenderHighlight = !sRenderHighlight; +} + +// static +BOOL LLPipeline::getRenderHighlights(void*) +{ + return sRenderHighlight; +} + +// static +BOOL LLPipeline::getProcessBeacons(void* data) +{ + return sRenderProcessBeacons; +} + LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision) { LLDrawable* drawable = mObjectPartition[PARTITION_VOLUME]->pickDrawable(start, end, collision); @@ -3633,8 +3778,12 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, BOOL reattach = FALSE; if (mCubeFrameBuffer == 0) { +#if !defined(__sparc) glGenFramebuffersEXT(1, &mCubeFrameBuffer); glGenRenderbuffersEXT(1, &mCubeDepth); +#else +#error Can we generalize this without a CPU architecture test? +#endif reattach = TRUE; } @@ -3705,6 +3854,7 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, if (reattach) { +#if !defined(__sparc) glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth); GLint res_x, res_y; glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &res_x); @@ -3716,15 +3866,22 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, } glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); +#else +#error Can we generalize this without a CPU architecture test? +#endif } for (S32 i = 0; i < 6; i++) { +#if !defined(__sparc) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, cube_face[i], cube_map->getGLName(), 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mCubeDepth); +#else +#error Can we generalize this without a CPU architecture test? +#endif glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.f, 1.f, 0.1f, 1024.f); @@ -3744,7 +3901,11 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, gPipeline.renderGeom(cube_cam); } +#if !defined(__sparc) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +#else +#error Can we generalize this without a CPU architecture test? +#endif cube_cam.setOrigin(origin); gPipeline.resetDrawOrders(); @@ -3953,10 +4114,14 @@ void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, LLGLDisable blend(GL_BLEND); LLGLDisable cull(GL_CULL_FACE); +#if !defined(__sparc) if (mFramebuffer[0] == 0) { glGenFramebuffersEXT(2, mFramebuffer); } +#else +#error Can we generalize this without a CPU architecture test? +#endif GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); @@ -3979,11 +4144,15 @@ void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, for (S32 i = 0; i < kernel; i++) { +#if !defined(__sparc) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebuffer[i%2]); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, i%2 == 0 ? buffer : dest, 0); +#else +#error Can we generalize this without a CPU architecture test? +#endif glBindTexture(GL_TEXTURE_2D, i == 0 ? source : i%2==0 ? dest : @@ -4010,7 +4179,11 @@ void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, } +#if !defined(__sparc) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +#else +#error Can we generalize this without a CPU architecture test? +#endif gGlowProgram.unbind(); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); diff --git a/linden/indra/newview/pipeline.h b/linden/indra/newview/pipeline.h index a687e12..218f920 100644 --- a/linden/indra/newview/pipeline.h +++ b/linden/indra/newview/pipeline.h @@ -154,7 +154,6 @@ public: void postSort(LLCamera& camera); void forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*)); void forAllVisibleDrawables(void (*func)(LLDrawable*)); - static void highlightPhysical(LLDrawable* drawablep); void renderObjects(U32 type, U32 mask, BOOL texture = TRUE); @@ -207,18 +206,36 @@ public: static BOOL toggleRenderDebugControl(void* data); static BOOL toggleRenderDebugFeatureControl(void* data); + static void setRenderParticleBeacons(BOOL val); static void toggleRenderParticleBeacons(void* data); static BOOL getRenderParticleBeacons(void* data); + static void setRenderSoundBeacons(BOOL val); static void toggleRenderSoundBeacons(void* data); static BOOL getRenderSoundBeacons(void* data); + static void setRenderPhysicalBeacons(BOOL val); static void toggleRenderPhysicalBeacons(void* data); static BOOL getRenderPhysicalBeacons(void* data); + static void setRenderScriptedBeacons(BOOL val); static void toggleRenderScriptedBeacons(void* data); static BOOL getRenderScriptedBeacons(void* data); + static void setRenderScriptedTouchBeacons(BOOL val); + static void toggleRenderScriptedTouchBeacons(void* data); + static BOOL getRenderScriptedTouchBeacons(void* data); + + static void setRenderBeacons(BOOL val); + static void toggleRenderBeacons(void* data); + static BOOL getRenderBeacons(void* data); + + static void setRenderHighlights(BOOL val); + static void toggleRenderHighlights(void* data); + static BOOL getRenderHighlights(void* data); + + static BOOL getProcessBeacons(void* data); + private: void initShaders(BOOL force); void unloadShaders(); @@ -494,8 +511,9 @@ protected: LLDrawPool* mBumpPool; // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar - +public: std::vector mHighlightFaces; // highlight faces on physical objects +protected: std::vector mSelectedFaces; LLPointer mFaceSelectImagep; @@ -508,9 +526,14 @@ protected: F32 mSunShadowFactor; static BOOL sRenderPhysicalBeacons; + static BOOL sRenderScriptedTouchBeacons; static BOOL sRenderScriptedBeacons; static BOOL sRenderParticleBeacons; static BOOL sRenderSoundBeacons; +public: + static BOOL sRenderBeacons; + static BOOL sRenderHighlight; + static BOOL sRenderProcessBeacons; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); diff --git a/linden/indra/newview/postbuild.bat b/linden/indra/newview/postbuild.bat index 76bedbe..d71a81e 100644 --- a/linden/indra/newview/postbuild.bat +++ b/linden/indra/newview/postbuild.bat @@ -10,7 +10,6 @@ goto end :debug echo copying debug files -if exist .\debug\freebl3.dll goto end copy ..\..\libraries\i686-win32\lib_debug\freebl3.dll .\debug\ /y copy ..\..\libraries\i686-win32\lib_debug\gksvggdiplus.dll .\debug\ /y copy ..\..\libraries\i686-win32\lib_debug\js3250.dll .\debug\ /y @@ -27,6 +26,18 @@ copy ..\..\libraries\i686-win32\lib_debug\xul.dll .\debug\ /y rem --- this is required for mozilla debug builds and displays the aborty/retry/ignore dialog on an assert - crashes without it --- copy ..\..\libraries\i686-win32\lib_debug\windbgdlg.exe .\debug\ /y +rem --- runtime pieces for the bHear stuff. +copy .\vivox-runtime\i686-win32\tntk.dll .\ /y +copy .\vivox-runtime\i686-win32\libeay32.dll .\ /y +copy .\vivox-runtime\i686-win32\SLVoice.exe .\ /y +copy .\vivox-runtime\i686-win32\ssleay32.dll .\ /y +copy .\vivox-runtime\i686-win32\SLVoiceAgent.exe .\ /y +copy .\vivox-runtime\i686-win32\srtp.dll .\ /y +copy .\vivox-runtime\i686-win32\alut.dll .\ /y +copy .\vivox-runtime\i686-win32\vivoxsdk.dll .\ /y +copy .\vivox-runtime\i686-win32\ortp.dll .\ /y +copy .\vivox-runtime\i686-win32\wrap_oal.dll .\ /y + @IF NOT EXIST ..\llkdu\Debug\llkdu.dll ( @IF EXIST ..\..\libraries\i686-win32\lib_debug\llkdu.dll ( SET KDU_DLL=..\..\libraries\i686-win32\lib_debug\llkdu.dll @@ -41,7 +52,6 @@ goto end :release echo copying release files -if exist .\Release\freebl3.dll goto end copy ..\..\libraries\i686-win32\lib_release\freebl3.dll .\Release\ /y copy ..\..\libraries\i686-win32\lib_release\gksvggdiplus.dll .\Release\ /y copy ..\..\libraries\i686-win32\lib_release\js3250.dll .\Release\ /y @@ -56,6 +66,18 @@ copy ..\..\libraries\i686-win32\lib_release\ssl3.dll .\Release\ /y copy ..\..\libraries\i686-win32\lib_release\xpcom.dll .\Release\ /y copy ..\..\libraries\i686-win32\lib_release\xul.dll .\Release\ /y +rem --- runtime pieces for the bHear stuff. +copy .\vivox-runtime\i686-win32\tntk.dll .\ /y +copy .\vivox-runtime\i686-win32\libeay32.dll .\ /y +copy .\vivox-runtime\i686-win32\SLVoice.exe .\ /y +copy .\vivox-runtime\i686-win32\ssleay32.dll .\ /y +copy .\vivox-runtime\i686-win32\SLVoiceAgent.exe .\ /y +copy .\vivox-runtime\i686-win32\srtp.dll .\ /y +copy .\vivox-runtime\i686-win32\alut.dll .\ /y +copy .\vivox-runtime\i686-win32\vivoxsdk.dll .\ /y +copy .\vivox-runtime\i686-win32\ortp.dll .\ /y +copy .\vivox-runtime\i686-win32\wrap_oal.dll .\ /y + @IF NOT EXIST ..\llkdu\Release\llkdu.dll ( copy ..\..\libraries\i686-win32\lib_release\llkdu.dll .\Release\ /y ) ELSE ( @@ -65,7 +87,6 @@ goto end :releasenoopt echo copying releasenoopt files -if exist .\ReleaseNoOpt\freebl3.dll goto end copy ..\..\libraries\i686-win32\lib_release\freebl3.dll .\ReleaseNoOpt\ /y copy ..\..\libraries\i686-win32\lib_release\gksvggdiplus.dll .\ReleaseNoOpt\ /y copy ..\..\libraries\i686-win32\lib_release\js3250.dll .\ReleaseNoOpt\ /y @@ -80,6 +101,18 @@ copy ..\..\libraries\i686-win32\lib_release\ssl3.dll .\ReleaseNoOpt\ /y copy ..\..\libraries\i686-win32\lib_release\xpcom.dll .\ReleaseNoOpt\ /y copy ..\..\libraries\i686-win32\lib_release\xul.dll .\ReleaseNoOpt\ /y +rem --- runtime pieces for the bHear stuff. +copy .\vivox-runtime\i686-win32\tntk.dll . /y +copy .\vivox-runtime\i686-win32\libeay32.dll . /y +copy .\vivox-runtime\i686-win32\SLVoice.exe . /y +copy .\vivox-runtime\i686-win32\ssleay32.dll . /y +copy .\vivox-runtime\i686-win32\SLVoiceAgent.exe . /y +copy .\vivox-runtime\i686-win32\srtp.dll . /y +copy .\vivox-runtime\i686-win32\alut.dll . /y +copy .\vivox-runtime\i686-win32\vivoxsdk.dll . /y +copy .\vivox-runtime\i686-win32\ortp.dll . /y +copy .\vivox-runtime\i686-win32\wrap_oal.dll . /y + @IF NOT EXIST ..\llkdu\ReleaseNoOpt\llkdu.dll ( copy ..\..\libraries\i686-win32\lib_release\llkdu.dll .\ReleaseNoOpt\ /y ) ELSE ( @@ -89,7 +122,6 @@ goto end :releasefordownload echo copying releasefordownload files -if exist .\ReleaseForDownload\freebl3.dll goto end copy ..\..\libraries\i686-win32\lib_release\freebl3.dll .\ReleaseForDownload\ /y copy ..\..\libraries\i686-win32\lib_release\gksvggdiplus.dll .\ReleaseForDownload\ /y copy ..\..\libraries\i686-win32\lib_release\js3250.dll .\ReleaseForDownload\ /y @@ -103,6 +135,18 @@ copy ..\..\libraries\i686-win32\lib_release\softokn3.dll .\ReleaseForDownload\ copy ..\..\libraries\i686-win32\lib_release\ssl3.dll .\ReleaseForDownload\ /y copy ..\..\libraries\i686-win32\lib_release\xpcom.dll .\ReleaseForDownload\ /y copy ..\..\libraries\i686-win32\lib_release\xul.dll .\ReleaseForDownload\ /y +rem --- runtime pieces for the bHear stuff. +copy .\vivox-runtime\i686-win32\tntk.dll .\ /y +copy .\vivox-runtime\i686-win32\libeay32.dll .\ /y +copy .\vivox-runtime\i686-win32\SLVoice.exe .\ /y +copy .\vivox-runtime\i686-win32\ssleay32.dll .\ /y +copy .\vivox-runtime\i686-win32\SLVoiceAgent.exe .\ /y +copy .\vivox-runtime\i686-win32\srtp.dll .\ /y +copy .\vivox-runtime\i686-win32\alut.dll .\ /y +copy .\vivox-runtime\i686-win32\vivoxsdk.dll .\ /y +copy .\vivox-runtime\i686-win32\ortp.dll .\ /y +copy .\vivox-runtime\i686-win32\wrap_oal.dll .\ /y + @IF NOT EXIST ..\llkdu\Release\llkdu.dll ( copy ..\..\libraries\i686-win32\lib_release\llkdu.dll .\ReleaseForDownload\ /y ) ELSE ( diff --git a/linden/indra/newview/releasenotes.txt b/linden/indra/newview/releasenotes.txt index 34b68c6..a1454be 100644 --- a/linden/indra/newview/releasenotes.txt +++ b/linden/indra/newview/releasenotes.txt @@ -1,3 +1,80 @@ +Release Notes for Second Life 1.18.1(2) August 2, 2007 +===================================== + +New Features: +* In-World Voice Chat +** In-world Voice Chat is now part of the main viewer. +** You can see and manage all voice settings in Edit > Preferences > Voice Chat. +** Voice is off by default. To enable (and disable) voice, visit Edit > Preferences > Voice Chat and check/uncheck the box beside "Enable voice chat". +** A voice set-up wizard appears during first voice use to help residents set up voice and adjust their mic volume and tuning. You should run the voice set-up wizard even if you only want the ability to hear others and do not wish to speak. +** Push-to-Talk is part of the Voice feature. Push-to-Talk is ON by default, which means Resident mics are OFF by default. +** Speech gestures for voice are included in the Library, in Gestures > Speech Gestures. These gestures need to be activated in order to work; they are off by default. +* Streaming video support for Linux client. + +Changes: +* Shortcut keys for menu items in the Client & Server menus are now disabled if the menus are hidden. +* Text from objects can be muted. + +Bug fixes: +* VWR-1797: Remove mention of "Live Help" from Crash Logger +* VWR-1732: Pressing Enter, with multiple inventory objects selected, crashes viewer +* VWR-1729: indra/lscript/lscript_compile/indra.l: avoid yyunput hack on Windows build +* VWR-1723: Possible crash in llvopartgroup +* VWR-1706: Minor quirk (and cleanup) in llfloater.cpp +* VWR-1705: indra/lscript/lscript_compile/indra.y: disable compiler warning #4065 for 'switch' statements +* VWR-1704: indra/llui/files.lst: delete llhtmlhelp.h entry +* VWR-1698: Clean up parcel flag manipulation +* VWR-1655: Script Warnings/errors window is hard to resize, resets size after closing tabs. +* VWR-1646: Possible crash when login server is unavailable. +* VWR-1626: Patch to avoid IM window from resizing when sessions open or close +* VWR-1613: Overuse of virtual +* VWR-1612: LLRenderPass::Pushbatch and LLViewerImage::addTextureStats tuning +* VWR-1586: Mismatched delete in llviewerparcelmgr.cpp +* VWR-1578: Two quirks in IM regarding "xxxx is typing" +* VWR-1471: Inspect (Pie menu > More > More > Inspect) shows nothing on first use when "only select own objects" is enabled +* VWR-1470: Buttons (IM, Teleport, Profile, ...) in friends list are disabled when opening friends list window +* VWR-1468: LoginPacketNeverReceived dialog text is incorrect +* VWR-1462: Order of right-click menu on Inventory is confusing +* VWR-1453: A few old-school changes for llviewerregion.cpp +* VWR-1434: Null pointer crash when terraforming +* VWR-1406: Unchecking "Go Away/AFK when idle" has no effect in 1.17.2.0 +* VWR-1382: Some scripted objects are highlighted in red while pressing Alt with tools open +* VWR-1381: libpng12.a for MacOS X is missing in 1.17.1.0 and build fails. +* VWR-1358: Physical objects remain red if tools window is closed while holding Alt key +* VWR-1358: Physical objects remain red if tools window is closed while holding Alt key +* VWR-1353: Misleading variable names in LLTextEditor +* VWR-1344: Reverse order of popups, so that new ones appear underneath existing ones rather than on top. +* VWR-1318: Selecting Cancel while saving a snapshot to disk still triggers snapshot gesture +* VWR-1314: Multiple selection then individual deselection of attachments broken +* VWR-1294: Possibly threads not fully cleaned up at end of program +* VWR-1289: On logging in, sound volume for stream is low, despite the actual setting in the music control +* VWR-1282: Better error handling when fonts are missing +* VWR-1270: Script error window keeps reverting to a very small size +* VWR-1246: Mac: File menu > Snapshot to Disk lists wrong shortcut key +* VWR-1105: Set internal limit of particle count to max value from GUI preferences. +* VWR-1092: Disable mouse hover text on HUDs, since it always only shows the owner's name and generally gets in the way of HUD functionality. +* VWR-727: Torn of IM windows should be minimizable (was re: VWR-233: ... resizeable and minimizable) +* VWR-447: Allow minimized windows to be repositioned in client +* VWR-353: Rebake command - add a keyboard shortcut and put in tools menu +* VWR-349: Change keyboard shortcuts, because entering { [ ] } on German and some other international keyboards (AltGr 7, 8, 9, 0) triggers Rendering Features accelerators Ctrl-Alt-7, 8, 9, 0 (previously resulting in unstable viewer) +* VWR-238: Permissions of Roles and Rights in the german version are mased up. +* VWR-102: md5 slow +* SVC-371: Fix the legibility and grammar/consistency of the new llOwnerSay implementation +* SVC-193: llParticleSystem - halo of rogue particles around original particle system after 1.15 update* SVC-373: Deleting a script's code results in a non-existent file and "missing from database" error +* Fixed preference for showing or hiding server combo box was not preserved +* Fixed residents with negative L$ balance can't purchase items set for sale "Original" or "Copy" that are being sold for L$0 +* "Copy SLURL to clipboard" is now enabled for an avatar's current coordinates +* Macintosh viewer now correctly opens the map and selects the destination on a SLURL request +* Leading and trailing spaces are now automatically trimmed from parcel media URLs +* Corrected the spacing of the yellow "next dialog" chevron (was partially blocked by the Mute button) +* Corrected the error message shown when adding 11th Estate Manager +* Added CPU detection for Intel Core Duo/Solo and Intel Core 2 Duo +* "Set Window Size..." setting is now correctly resumed after being minimized +* Added link to Qa wiki in the viewer bug reporter menu. +* Updated text in Second Life Crash Logger with new support portal information +* Corrected an issue with UI font scaling in the bug reporter window + + Release Notes for Second Life 1.18.0(6) July 11, 2007 ===================================== Changes: @@ -43,9 +120,6 @@ Release Notes for Second Life 1.17.2(0) June 27, 2007 Bug fixes: * VWR-1369: Creating, re-rezzing, then editing an object results in a viewer crash -Not for public: -* SL-46373 VWR-1369: Creating, re-rezzing, then editing an object results in a viewer crash - Release Notes for Second Life 1.17.1(0) June 25, 2007 ===================================== diff --git a/linden/indra/newview/res/newViewRes.rc b/linden/indra/newview/res/newViewRes.rc index b1992cf..9a86533 100644 --- a/linden/indra/newview/res/newViewRes.rc +++ b/linden/indra/newview/res/newViewRes.rc @@ -227,8 +227,8 @@ TOOLPIPETTE CURSOR "toolpipette.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,18,0,6 - PRODUCTVERSION 1,18,0,6 + FILEVERSION 1,18,1,2 + PRODUCTVERSION 1,18,1,2 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -245,12 +245,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "1.18.0.6" + VALUE "FileVersion", "1.18.1.2" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright 2001-2007, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "1.18.0.6" + VALUE "ProductVersion", "1.18.1.2" END END BLOCK "VarFileInfo" diff --git a/linden/indra/newview/secondlife setup build firstlook.bat b/linden/indra/newview/secondlife setup build firstlook.bat deleted file mode 100644 index 73e47ec..0000000 --- a/linden/indra/newview/secondlife setup build firstlook.bat +++ /dev/null @@ -1,4 +0,0 @@ -@rem Invoke the script which preps then runs the installer. -@rem This batch file is customized per grid. - -@"secondlife setup build.bat" --grid=firstlook diff --git a/linden/indra/newview/secondlife setup build voicebeta.bat b/linden/indra/newview/secondlife setup build voicebeta.bat new file mode 100644 index 0000000..293cf82 --- /dev/null +++ b/linden/indra/newview/secondlife setup build voicebeta.bat @@ -0,0 +1,4 @@ +@rem Invoke the script which preps then runs the installer. +@rem This batch file is customized per grid. + +@"secondlife setup build.bat" --grid=aditi --channel="Second Life Voice Beta" diff --git a/linden/indra/newview/secondlife setup build voicefirstlook.bat b/linden/indra/newview/secondlife setup build voicefirstlook.bat new file mode 100644 index 0000000..ebb74ea --- /dev/null +++ b/linden/indra/newview/secondlife setup build voicefirstlook.bat @@ -0,0 +1,4 @@ +@rem Invoke the script which preps then runs the installer. +@rem This batch file is customized per grid. + +@"secondlife setup build.bat" --channel="Second Life Voice First Look" diff --git a/linden/indra/newview/skins/textures/textures.xml b/linden/indra/newview/skins/textures/textures.xml index 79e910a..1c02ce4 100644 --- a/linden/indra/newview/skins/textures/textures.xml +++ b/linden/indra/newview/skins/textures/textures.xml @@ -304,6 +304,7 @@ + @@ -314,6 +315,8 @@ + + @@ -391,5 +394,22 @@ + + + + + + + + + + + + + + + + + + - diff --git a/linden/indra/newview/skins/xui/de/role_actions.xml b/linden/indra/newview/skins/xui/de/role_actions.xml index d907591..4265342 100644 --- a/linden/indra/newview/skins/xui/de/role_actions.xml +++ b/linden/indra/newview/skins/xui/de/role_actions.xml @@ -5,39 +5,39 @@ name="Membership"> + name="member invite" value="1" /> + name="member eject" value="2" /> + name="member options" value="3" /> + name="role create" value="4" /> + name="role delete" value="5" /> + name="role properties" value="6" /> + name="role assign member limited" value="7" /> + name="role assign member" value="8" /> + name="role remove member" value="9" /> + name="role change actions" value="10" /> + name="land deed" value="12" /> + name="land release" value="13" /> + name="land set sale info" value="14" /> + name="land divide join" value="15" /> + name="land find places" value="17" /> + name="land change identity" value="18" /> + name="land set landing point" value="19" /> + name="land change media" value="20" /> + name="land edit" value="21" /> + name="land options" value="22" /> + name="land allow edit land" value="23" /> + name="land allow fly" value="24" /> + name="land allow create" value="25" /> + name="land allow landmark" value="26" /> + name="land allow set home" value="28" /> + name="land manage allowed" value="29" /> + name="land manage banned" value="30" /> + name="land manage passes" value="31" /> + name="land admin" value="32" /> + name="land return group owned" value="48" /> + name="land return group set" value="33" /> + name="land return non group" value="34" /> + name="land gardening" value="35" /> + name="object deed" value="36" /> + name="object manipulate" value="38" /> + name="object set sale" value="39" /> + name="accounting accountable" value="40" /> + name="notices send" value="42" /> + name="notices receive" value="43" /> + name="proposal start" value="44" /> + name="proposal vote" value="45" /> diff --git a/linden/indra/newview/skins/xui/en-us/alerts.xml b/linden/indra/newview/skins/xui/en-us/alerts.xml index 319e495..d294ae8 100644 --- a/linden/indra/newview/skins/xui/en-us/alerts.xml +++ b/linden/indra/newview/skins/xui/en-us/alerts.xml @@ -1087,7 +1087,7 @@ for advice and a link to the system status web page. - Unable to connect. No reply from login database. + Unable to connect. No login ack from simulator. Please try again in a few minutes, or click Help for advice and a link to the system status web page. @@ -2594,7 +2594,7 @@ and the default for the 'Revert' tool? - You can only have [MAX_MANAGER] Banned Residents. + You can only have [MAX_MANAGER] Estate Managers. @@ -2794,6 +2794,20 @@ also appear higher when people search for keywords. Cancel + + + Visit the [SECOND_LIFE] QA Wiki. + + + When launching web browser to view the QA Wiki + + + + Visit the [SECOND_LIFE] Public Issue Tracker, Where you can Report Bugs and other Issues. @@ -3826,6 +3840,20 @@ Default: off regardless of any other settings. + + + Parcels in this estate are allowed to have their own voice + channels in which residents may hear and talk with others + nearby. + + Default: off + + + + +This version of Second Life is not compatible with the Voice Chat feature in this region. In order for Voice Chat to function correctly you will need to update Second Life. + + Setting an estate covenant enables you to sell parcels @@ -4082,7 +4110,7 @@ will only work if a script is added with a money() event. Visit the Second Life Support Web site? - Ignore + When visiting the Second Life Support Website. - Use this tool to *only* report technical features that do not perform as -described or expected, please provide as much detail as possible, You -may reply to the auto-response email to add more details to your report. +Use this tool to *only* report technical features that do not perform +as described or expected, please provide as much detail as possible, +You may reply to the auto-response email to add more details to your +report. All bug reports are investigated and assessed. No email response will be sent. - If you are having a technical difficulty, please contact Support at: @@ -4338,25 +4367,25 @@ the contents of your Lost And Found folder? When copying a SLURL to your clipboard - + - Error starting a new IM session with [RECIPIENT]. + Error starting a new chat session with [RECIPIENT]. [REASON] - + - Error starting a new IM session with [RECIPIENT]. + Error starting a new chat session with [RECIPIENT]. [REASON] - + Error [EVENT] [RECIPIENT]. [REASON] @@ -4365,9 +4394,9 @@ the contents of your Lost And Found folder? OK - + - Your IM session with [NAME] must close. + Your chat session with [NAME] must close. [REASON]