aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorArmin Weatherwax2009-07-01 23:22:56 +0200
committerArmin Weatherwax2009-07-11 13:43:22 +0200
commit0b661f028e446ab4f19959129f3209f1a29fd63e (patch)
tree2f1ab27163104727ed972ab55c0680b0a37a8637
parentBROKEN logoff/relog crashing inconsistently on various startup states. (diff)
downloadmeta-impy-0b661f028e446ab4f19959129f3209f1a29fd63e.zip
meta-impy-0b661f028e446ab4f19959129f3209f1a29fd63e.tar.gz
meta-impy-0b661f028e446ab4f19959129f3209f1a29fd63e.tar.bz2
meta-impy-0b661f028e446ab4f19959129f3209f1a29fd63e.tar.xz
BROKEN now consistantly crashes at startup STATE_PRECACHE
-rw-r--r--Imprudence.log581
-rw-r--r--linden/indra/newview/llworld.cpp1
-rw-r--r--mAttachedObject.diff.txt16
-rw-r--r--meerkat-llmenugl.diff.txt534
-rw-r--r--meerkat-message.diff.txt1319
-rw-r--r--meerkat-pipeline.cpp.diff.txt22
-rw-r--r--meerkat-voice.diff.txt7282
-rw-r--r--stack_trace.log32
8 files changed, 9787 insertions, 0 deletions
diff --git a/Imprudence.log b/Imprudence.log
new file mode 100644
index 0000000..3bc56eb
--- /dev/null
+++ b/Imprudence.log
@@ -0,0 +1,581 @@
12009-07-01T20:58:49Z INFO: initConfiguration: Loading settings file list/home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings_files.xml
22009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings_crash_behavior.xml
32009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings.xml
42009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings_per_account.xml
52009-07-01T20:58:49Z INFO: initParseCommandLine: Language de
62009-07-01T20:58:49Z INFO: initParseCommandLine: Location DE
72009-07-01T20:58:49Z INFO: initParseCommandLine: Variant UTF-8
82009-07-01T20:58:49Z INFO: initConfiguration: Using command line specified settings filename: /home/aw/.imprudence/user_settings/settings_imprudence.xml
92009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/user_settings/settings_crash_behavior.xml
102009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/user_settings/settings_imprudence.xml
112009-07-01T20:58:49Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/user_settings/settings_per_account.xml to load.
122009-07-01T20:58:49Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/user_settings/settings_per_account.xml - No settings found.
132009-07-01T20:58:49Z INFO: getFontListSans: Getting system font list from FontConfig...
142009-07-01T20:58:49Z INFO: getFontListSans: Language de
152009-07-01T20:58:49Z INFO: getFontListSans: Location DE
162009-07-01T20:58:49Z INFO: getFontListSans: Variant UTF-8
172009-07-01T20:58:49Z INFO: getFontListSans: Preferring fonts of language: de
182009-07-01T20:58:49Z INFO: getFontListSans: Using 31 system font(s).
192009-07-01T20:58:49Z INFO: parseFile: Loading grid info file /home/aw/.imprudence/user_settings/grid_info.xml.
202009-07-01T20:58:49Z INFO: parseData: Loading grid data.
212009-07-01T20:58:49Z WARNING: setPlatform: Unknown platform 'Other'.
222009-07-01T20:58:49Z INFO: parseFile: Loading grid info file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/default_grids.xml.
232009-07-01T20:58:49Z INFO: parseUrl: Loading grid info from 'http://opensim-viewer.sourceforge.net/db/grids.php'.
242009-07-01T20:58:49Z INFO: blockingGet: blockingGet of http://opensim-viewer.sourceforge.net/db/grids.php
252009-07-01T20:58:51Z WARNING: setCurrentGrid: Unknown grid ''. Setting to default grid.
262009-07-01T20:58:51Z INFO: initMarkerFile: Last exec LLError crashed, setting LastExecEvent to 2
272009-07-01T20:58:51Z INFO: initMarkerFile: Last exec crashed, setting LastExecEvent to 3
282009-07-01T20:58:51Z INFO: writeSystemInfo:
292009-07-01T20:58:51Z INFO: writeSystemInfo: Local time: 2009-07-01T22:58:51 CEST
302009-07-01T20:58:51Z INFO: writeSystemInfo: CPU info:
31processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 14 model name : Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz stepping : 12 cpu MHz : 798.000 cache size : 2048 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe constant_tsc arch_perfmon bts pni monitor est tm2 xtpr pdcm bogomips : 3990.13 clflush size : 64 power management: processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 14 model name : Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz stepping : 12 cpu MHz : 798.000 cache size : 2048 KB physical id : 0 siblings : 2 core id : 1 cpu cores : 2 apicid : 1 initial apicid : 1 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe constant_tsc arch_perfmon bts pni monitor est tm2 xtpr pdcm bogomips : 3990.49 clflush size : 64 power management:
32->mHasSSE: 1
33->mHasSSE2: 1
34->mHasAltivec: 0
35->mCPUMhz: 798
36->mCPUString: Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz
37
382009-07-01T20:58:51Z INFO: writeSystemInfo: Memory info:
39MemTotal: 1945568 kB MemFree: 593720 kB Buffers: 13392 kB Cached: 580556 kB SwapCached: 2340 kB Active: 79892 kB Inactive: 810692 kB Active(anon): 17656 kB Inactive(anon): 280332 kB Active(file): 62236 kB Inactive(file): 530360 kB Unevictable: 0 kB Mlocked: 0 kB HighTotal: 1056424 kB HighFree: 133548 kB LowTotal: 889144 kB LowFree: 460172 kB SwapTotal: 995988 kB SwapFree: 959280 kB Dirty: 100 kB Writeback: 0 kB AnonPages: 294600 kB Mapped: 61736 kB Slab: 26508 kB SReclaimable: 17520 kB SUnreclaim: 8988 kB PageTables: 2868 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 1968772 kB Committed_AS: 504844 kB VmallocTotal: 122880 kB VmallocUsed: 18444 kB VmallocChunk: 103592 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 4096 kB DirectMap4k: 876536 kB DirectMap4M: 32768 kB
402009-07-01T20:58:51Z INFO: writeSystemInfo: OS: Linux 2.6
412009-07-01T20:58:51Z INFO: writeSystemInfo: OS info: Linux 2.6.29.3 #1 SMP Fri May 15 17:03:02 CEST 2009 i686
422009-07-01T20:58:51Z INFO: writeDebugInfo: Opening debug file /home/aw/.imprudence/logs/debug_info.log
432009-07-01T20:58:51Z INFO: init: J2C Engine is: OpenJPEG: 1.2.0, Runtime: 1.3.0
442009-07-01T20:58:51Z INFO: init: libcurl version is: libcurl/7.16.4 OpenSSL/0.9.7c zlib/1.2.3.3 c-ares/1.4.0
452009-07-01T20:58:51Z INFO: updateVectorize: Vectorization : DISABLED
462009-07-01T20:58:51Z INFO: updateVectorize: Vector Processor : COMPILER DEFAULT
472009-07-01T20:58:51Z INFO: updateVectorize: Vectorized Skinning : DISABLED
482009-07-01T20:58:51Z WARNING: isFeatureAvailable: Feature RenderCubeMap not on feature list!
492009-07-01T20:58:51Z INFO: grab_dbus_syms: Found DSO: libdbus-glib-1.so.2
502009-07-01T20:58:51Z INFO: initCache: Headers: 139810 Textures size: 320 MB
512009-07-01T20:58:51Z INFO: purgeTextures: TEXTURE CACHE: PURGED: 0 ENTRIES: 2650 CACHE SIZE: 65 MB
522009-07-01T20:58:51Z INFO: initCache: VFS CACHE SIZE: 100 MB
532009-07-01T20:58:51Z WARNING: LLVFS: Using index file /home/aw/.imprudence/cache/index.db2.x.1
542009-07-01T20:58:51Z WARNING: LLVFS: Using data file /home/aw/.imprudence/cache/data.db2.x.1
552009-07-01T20:58:51Z WARNING: LLVFS: Using index file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/static_index.db2
562009-07-01T20:58:51Z WARNING: LLVFS: Using data file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/static_data.db2
572009-07-01T20:58:51Z INFO: initWindow: Initializing window...
582009-07-01T20:58:51Z INFO: ll_try_gtk_init: Starting GTK Initialization.
592009-07-01T20:58:51Z INFO: ll_try_gtk_init: GTK Initialized.
602009-07-01T20:58:51Z INFO: ll_try_gtk_init: - Compiled against GTK version 2.4.14
612009-07-01T20:58:51Z INFO: ll_try_gtk_init: - Running against GTK version 2.16.1
622009-07-01T20:58:51Z INFO: createContext: createContext, fullscreen=0 size=1118x722
632009-07-01T20:58:52Z INFO: createContext: Compiled against SDL 1.2.5
642009-07-01T20:58:52Z INFO: createContext: Running against SDL 1.2.12
652009-07-01T20:58:52Z INFO: createContext: createContext: creating window 1118x722x32
662009-07-01T20:58:54Z INFO: x11_detect_VRAM_kb: Looking in /var/log/Xorg.0.log for VRAM info...
672009-07-01T20:58:54Z INFO: createContext: GL buffer:
682009-07-01T20:58:54Z INFO: createContext: Red Bits 8
692009-07-01T20:58:54Z INFO: createContext: Green Bits 8
702009-07-01T20:58:54Z INFO: createContext: Blue Bits 8
712009-07-01T20:58:54Z INFO: createContext: Alpha Bits 8
722009-07-01T20:58:54Z INFO: createContext: Depth Bits 24
732009-07-01T20:58:54Z INFO: createContext: Stencil Bits 8
742009-07-01T20:58:54Z INFO: initExtensions: Couldn't initialize GL_ARB_point_parameters
752009-07-01T20:58:54Z INFO: initExtensions: Disabling mip-map generation for ATI GPUs (performance opt)
762009-07-01T20:58:54Z WARNING: addFeature: LLFeatureList::Attempting to add preexisting feature Disregard128DefaultDrawDistance
772009-07-01T20:58:54Z INFO: loadGPUClass: GPU is ATI Radeon Xpress
782009-07-01T20:58:54Z INFO: applyBaseMasks: Setting GPU Class to Class0
792009-07-01T20:58:54Z WARNING: LLViewerImageList::getMaxVideoRamSetting: VRAM amount not detected, defaulting to 128 MB
802009-07-01T20:58:54Z WARNING: LLViewerImageList::getMaxVideoRamSetting: VRAM amount not detected, defaulting to 512 MB
812009-07-01T20:58:54Z INFO: LLViewerImageList::updateMaxResidentTexMem: Total Video Memory set to: 128 MB
822009-07-01T20:58:54Z INFO: LLViewerImageList::updateMaxResidentTexMem: Available Texture Memory set to: 96 MB
832009-07-01T20:58:55Z INFO: restoreGL: Loading bumpmap: <blahblah> from viewerart
842009-07-01T20:58:56Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
852009-07-01T20:58:56Z INFO: setShaders:
86~~~~~~~~~~~~~~~~~~
87 Loading Shaders:
88~~~~~~~~~~~~~~~~~~
892009-07-01T20:58:56Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
902009-07-01T20:58:57Z INFO: printGLInfoString: GL_VENDOR: ATI Technologies Inc.
912009-07-01T20:58:57Z INFO: printGLInfoString: GL_RENDERER: ATI Radeon Xpress Series
922009-07-01T20:58:57Z INFO: printGLInfoString: GL_VERSION: 2.1.8543 Release
932009-07-01T20:58:57Z WARNING: init: ndof_init_first FAILED
942009-07-01T20:58:57Z INFO: init: ndof: mDriverState=0; mNdofDev=0x9c2c1740; libinit=1
952009-07-01T20:58:57Z INFO: LLTemplateParser: ### Message template version 2 ###
962009-07-01T20:58:57Z INFO: start_net: startNet - receive buffer size : 262142
972009-07-01T20:58:57Z INFO: start_net: startNet - send buffer size : 262142
982009-07-01T20:58:57Z INFO: idle_startup: Message System Initialized.
992009-07-01T20:58:57Z INFO: init: LLAudioEngine::init() AudioEngine successfully initialized
1002009-07-01T20:58:57Z INFO: init: LLAudioEngine_OpenAL::init() OpenAL successfully initialized
1012009-07-01T20:58:57Z INFO: init: OpenAL version: 1.1
1022009-07-01T20:58:57Z INFO: init: OpenAL vendor: OpenAL Community
1032009-07-01T20:58:57Z INFO: init: OpenAL renderer: OpenAL Soft
1042009-07-01T20:58:57Z INFO: init: ALUT version: 1.1
1052009-07-01T20:58:57Z INFO: init: ALC version: 1.1
1062009-07-01T20:58:57Z INFO: init: ALC default device: ALSA Software on default
1072009-07-01T20:58:57Z INFO: idle_startup: Audio Engine Initialized.
1082009-07-01T20:58:57Z INFO: setStartupState: Startup state changing from STATE_FIRST to (state #1)
1092009-07-01T20:58:59Z INFO: updateBrowserUserAgent: SecondLife/1.22.11.0 (Imprudence; default skin)
1102009-07-01T20:58:59Z INFO: setStartupState: Startup state changing from (state #1) to STATE_LOGIN_SHOW
1112009-07-01T20:58:59Z INFO: login_show: Initializing Login Screen
1122009-07-01T20:59:00Z INFO: setStartupState: Startup state changing from STATE_LOGIN_SHOW to STATE_LOGIN_WAIT
1132009-07-01T20:59:00Z WARNING: getChild: Found child named Say but of wrong type
1142009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Say in chat_bar
1152009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named end_call_btn in voice_remote
1162009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy text named channel_label in voice_remote
1172009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named voice_channel_bg in voice_remote
1182009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named appearance_btn in toolbar
1192009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named clothing_btn in toolbar
1202009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named sit_btn in toolbar
1212009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named History in chat_panel
1222009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy combo_box named Gesture in chat_panel
1232009-07-01T20:59:00Z WARNING: getChild: Found child named Say but of wrong type
1242009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Say in chat_panel
1252009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Chat in chat floater
1262009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named bandwidth_tooltip in status
1272009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named packet_loss_tooltip in status
1282009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named friend_name_label in friends
1292009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named friend_rights in friends
1302009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy text named process_rights_label in friends
1312009-07-01T20:59:01Z WARNING: createDummyWidget: Making dummy view named Shout in chat_bar
1322009-07-01T20:59:03Z INFO: setStartupState: Startup state changing from STATE_LOGIN_WAIT to STATE_LOGIN_CLEANUP
1332009-07-01T20:59:04Z INFO: idle_startup: Attempting login as: Armin Weatherwax <uuid>
1342009-07-01T20:59:04Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml to load.
1352009-07-01T20:59:04Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml - No settings found.
1362009-07-01T20:59:04Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings.xml to load.
1372009-07-01T20:59:04Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings.xml - No settings found.
1382009-07-01T20:59:04Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/armin_weatherwax/settings_per_account.xml
1392009-07-01T20:59:04Z INFO: loadFile: Loading history.xml file at url_history.xml
1402009-07-01T20:59:04Z INFO: loadFile: file missing, ill-formed, or simply undefined; not changing the file
1412009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_CLEANUP to STATE_LOGIN_AUTH_INIT
1422009-07-01T20:59:05Z INFO: rewriteURI: Rewriting http://127.0.0.1:9000/
1432009-07-01T20:59:05Z INFO: rewriteResult: [0] http://127.0.0.1:9000/
1442009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTH_INIT to STATE_LOGIN_AUTHENTICATE
1452009-07-01T20:59:05Z INFO: authenticate: Authenticating: Armin Weatherwax,
1462009-07-01T20:59:05Z INFO: authenticate: Options: inventory-root, inventory-skeleton, inventory-lib-root, inventory-lib-owner, inventory-skel-lib, initial-outfit, gestures, event_categories, event_notifications, classified_categories, buddy-list, ui-config, tutorial_setting, login-flags, global-textures, END
1472009-07-01T20:59:05Z INFO: authenticate: LLUserAuth::authenticate: uri=http://127.0.0.1:9000/
1482009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTHENTICATE to STATE_LOGIN_NO_DATA_YET
1492009-07-01T20:59:05Z INFO: transferRate: Buffer size: 105394 B
1502009-07-01T20:59:05Z INFO: transferRate: Transfer rate: 2041.61 Kb/s
1512009-07-01T20:59:05Z INFO: authResponse: Processed response: 0
1522009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING
1532009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_DOWNLOADING to STATE_LOGIN_PROCESS_RESPONSE
1542009-07-01T20:59:05Z INFO: addCircuitData: LLCircuit::addCircuitData for 127.0.0.1:9000
1552009-07-01T20:59:05Z INFO: saveFile: Saved grids to /home/aw/.imprudence/user_settings/grid_info.xml
1562009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_PROCESS_RESPONSE to STATE_WORLD_INIT
1572009-07-01T20:59:05Z INFO: LLVoiceClient::userAuthorized: name "Armin Weatherwax" , ID <uuid>
1582009-07-01T20:59:05Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
1592009-07-01T20:59:05Z INFO: loadPresets: Loading Default WindLight settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/
1602009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Blue%20Midday.xml
1612009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D9AM.xml
1622009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Sheer%20Surreality.xml
1632009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D12PM.xml
1642009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Funky%20Funky%20Funky.xml
1652009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Fine%20Day.xml
1662009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D3PM.xml
1672009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%203.xml
1682009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Funky%20Funky.xml
1692009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Night.xml
1702009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Coastal%20Sunset.xml
1712009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D9PM.xml
1722009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Barcelona.xml
1732009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D6AM.xml
1742009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Purple.xml
1752009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D6PM.xml
1762009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Gelatto.xml
1772009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Incongruent%20Truths.xml
1782009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Fluffy%20Big%20Clouds.xml
1792009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%202.xml
1802009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Ghost.xml
1812009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Desert%20Sunset.xml
1822009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Default.xml
1832009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%204.xml
1842009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Blizzard.xml
1852009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Coastal%20Afternoon.xml
1862009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Foggy.xml
1872009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Sailor%27s%20Delight.xml
1882009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Pirate.xml
1892009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D3AM.xml
1902009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%201.xml
1912009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D12AM.xml
1922009-07-01T20:59:05Z INFO: loadPresets: Loading User WindLight settings from /home/aw/.imprudence/user_settings/windlight/skies/
1932009-07-01T20:59:05Z INFO: loadDayCycle: Loading DayCycle settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/days/Default.xml
1942009-07-01T20:59:05Z INFO: loadAllPresets: Loading Default water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/
1952009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Murky.xml
1962009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Pond.xml
1972009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Valdez.xml
1982009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Default.xml
1992009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Glassy.xml
2002009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Second%20Plague.xml
2012009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/SNAKE%21%21%21.xml
2022009-07-01T20:59:05Z INFO: loadAllPresets: Loading User water settings from /home/aw/.imprudence/user_settings/windlight/water/
2032009-07-01T20:59:05Z INFO: initVOClasses: Viewer Object size: 444
2042009-07-01T20:59:05Z INFO: addRegion: Adding new region (1000:1000)
2052009-07-01T20:59:05Z INFO: addRegion: Host: 127.0.0.1:9000
2062009-07-01T20:59:05Z INFO: idle_startup: Adding initial simulator { 256000, 256000, 0 }
2072009-07-01T20:59:05Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS/<uuid>/
2082009-07-01T20:59:05Z INFO: LLAgent::setRegion: Moving agent into region: located at 127.0.0.1:9000
2092009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_WORLD_INIT to (state #12)
2102009-07-01T20:59:05Z INFO: LLVoiceClient::stateMachine: /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/bin/SLVoice not found.
2112009-07-01T20:59:06Z DEBUG: startup: Found GStreamer plugins:
2122009-07-01T20:59:06Z DEBUG: startup: private-slvideoplugin, loaded? Yes
2132009-07-01T20:59:06Z DEBUG: startup: wavparse, loaded? No
2142009-07-01T20:59:06Z DEBUG: startup: mpegdemux2, loaded? No
2152009-07-01T20:59:06Z DEBUG: startup: uridecodebin, loaded? No
2162009-07-01T20:59:06Z DEBUG: startup: esdsink, loaded? No
2172009-07-01T20:59:06Z DEBUG: startup: ogg, loaded? No
2182009-07-01T20:59:06Z DEBUG: startup: ffmpeg, loaded? No
2192009-07-01T20:59:06Z DEBUG: startup: theora, loaded? No
2202009-07-01T20:59:06Z DEBUG: startup: gnomevfs, loaded? No
2212009-07-01T20:59:06Z DEBUG: startup: asf, loaded? No
2222009-07-01T20:59:06Z DEBUG: startup: coreelements, loaded? No
2232009-07-01T20:59:06Z DEBUG: startup: ossaudio, loaded? No
2242009-07-01T20:59:06Z DEBUG: startup: pulseaudio, loaded? No
2252009-07-01T20:59:06Z DEBUG: startup: coreindexers, loaded? No
2262009-07-01T20:59:06Z DEBUG: startup: typefindfunctions, loaded? No
2272009-07-01T20:59:06Z DEBUG: startup: autodetect, loaded? No
2282009-07-01T20:59:06Z DEBUG: startup: multifile, loaded? No
2292009-07-01T20:59:06Z DEBUG: startup: multipart, loaded? No
2302009-07-01T20:59:06Z DEBUG: startup: quicktime, loaded? No
2312009-07-01T20:59:06Z DEBUG: startup: id3demux, loaded? No
2322009-07-01T20:59:06Z DEBUG: startup: ffmpegcolorspace, loaded? No
2332009-07-01T20:59:06Z DEBUG: startup: audioconvert, loaded? No
2342009-07-01T20:59:06Z DEBUG: startup: tcp, loaded? No
2352009-07-01T20:59:06Z DEBUG: startup: audioresample, loaded? No
2362009-07-01T20:59:06Z DEBUG: startup: videoscale, loaded? No
2372009-07-01T20:59:06Z DEBUG: startup: avi, loaded? No
2382009-07-01T20:59:06Z DEBUG: startup: icydemux, loaded? No
2392009-07-01T20:59:06Z DEBUG: startup: vorbis, loaded? No
2402009-07-01T20:59:06Z DEBUG: startup: volume, loaded? No
2412009-07-01T20:59:06Z DEBUG: startup: playback, loaded? No
2422009-07-01T20:59:06Z DEBUG: startup: decodebin, loaded? No
2432009-07-01T20:59:06Z DEBUG: startup: alsa, loaded? No
2442009-07-01T20:59:06Z DEBUG: startup: udp, loaded? No
2452009-07-01T20:59:06Z DEBUG: startup: queue2, loaded? No
2462009-07-01T20:59:06Z DEBUG: startup: dvdsub, loaded? No
2472009-07-01T20:59:06Z DEBUG: startup: musicbrainz, loaded? No
2482009-07-01T20:59:06Z DEBUG: startup: wildmidi, loaded? No
2492009-07-01T20:59:06Z DEBUG: startup: rfbsrc, loaded? No
2502009-07-01T20:59:06Z DEBUG: startup: dvdlpcmdec, loaded? No
2512009-07-01T20:59:06Z DEBUG: startup: ofa, loaded? No
2522009-07-01T20:59:06Z DEBUG: startup: gstrtpmanager, loaded? No
2532009-07-01T20:59:06Z DEBUG: startup: dfbvideosink, loaded? No
2542009-07-01T20:59:06Z DEBUG: startup: fbdevsink, loaded? No
2552009-07-01T20:59:06Z DEBUG: startup: siddec, loaded? No
2562009-07-01T20:59:06Z DEBUG: startup: mpeg4videoparse, loaded? No
2572009-07-01T20:59:06Z DEBUG: startup: mpegvideoparse, loaded? No
2582009-07-01T20:59:06Z DEBUG: startup: nsfdec, loaded? No
2592009-07-01T20:59:06Z DEBUG: startup: festival, loaded? No
2602009-07-01T20:59:06Z DEBUG: startup: alsaspdif, loaded? No
2612009-07-01T20:59:06Z DEBUG: startup: mpegtsparse, loaded? No
2622009-07-01T20:59:06Z DEBUG: startup: a52dec, loaded? No
2632009-07-01T20:59:06Z DEBUG: startup: realmedia, loaded? No
2642009-07-01T20:59:06Z DEBUG: startup: dvdread, loaded? No
2652009-07-01T20:59:06Z DEBUG: startup: flvdemux, loaded? No
2662009-07-01T20:59:06Z DEBUG: startup: videosignal, loaded? No
2672009-07-01T20:59:06Z DEBUG: startup: sdp, loaded? No
2682009-07-01T20:59:06Z DEBUG: startup: mms, loaded? No
2692009-07-01T20:59:06Z DEBUG: startup: spcdec, loaded? No
2702009-07-01T20:59:06Z DEBUG: startup: speed, loaded? No
2712009-07-01T20:59:06Z DEBUG: startup: interleave, loaded? No
2722009-07-01T20:59:06Z DEBUG: startup: oss4, loaded? No
2732009-07-01T20:59:06Z DEBUG: startup: dvb, loaded? No
2742009-07-01T20:59:06Z DEBUG: startup: h264parse, loaded? No
2752009-07-01T20:59:06Z DEBUG: startup: bayer, loaded? No
2762009-07-01T20:59:06Z DEBUG: startup: dc1394, loaded? No
2772009-07-01T20:59:06Z DEBUG: startup: vcdsrc, loaded? No
2782009-07-01T20:59:06Z DEBUG: startup: tta, loaded? No
2792009-07-01T20:59:06Z DEBUG: startup: speexresample, loaded? No
2802009-07-01T20:59:06Z DEBUG: startup: mpeg2dec, loaded? No
2812009-07-01T20:59:06Z DEBUG: startup: gstinterlace, loaded? No
2822009-07-01T20:59:06Z DEBUG: startup: nuvdemux, loaded? No
2832009-07-01T20:59:06Z DEBUG: startup: faad, loaded? No
2842009-07-01T20:59:06Z DEBUG: startup: ladspa, loaded? No
2852009-07-01T20:59:06Z DEBUG: startup: mad, loaded? No
2862009-07-01T20:59:06Z DEBUG: startup: soundtouch, loaded? No
2872009-07-01T20:59:06Z DEBUG: startup: iec958, loaded? No
2882009-07-01T20:59:06Z DEBUG: startup: cdxaparse, loaded? No
2892009-07-01T20:59:06Z DEBUG: startup: sndfile, loaded? No
2902009-07-01T20:59:06Z DEBUG: startup: filter, loaded? No
2912009-07-01T20:59:06Z DEBUG: startup: replaygain, loaded? No
2922009-07-01T20:59:06Z DEBUG: startup: gsm, loaded? No
2932009-07-01T20:59:06Z DEBUG: startup: cdaudio, loaded? No
2942009-07-01T20:59:06Z DEBUG: startup: metadata, loaded? No
2952009-07-01T20:59:06Z DEBUG: startup: freeze, loaded? No
2962009-07-01T20:59:06Z DEBUG: startup: mve, loaded? No
2972009-07-01T20:59:06Z DEBUG: startup: jack, loaded? No
2982009-07-01T20:59:06Z DEBUG: startup: mpegaudioparse, loaded? No
2992009-07-01T20:59:06Z DEBUG: startup: dtsdec, loaded? No
3002009-07-01T20:59:06Z DEBUG: startup: selector, loaded? No
3012009-07-01T20:59:06Z DEBUG: startup: dvdspu, loaded? No
3022009-07-01T20:59:06Z DEBUG: startup: real, loaded? No
3032009-07-01T20:59:06Z DEBUG: startup: musepack, loaded? No
3042009-07-01T20:59:06Z DEBUG: startup: neon, loaded? No
3052009-07-01T20:59:06Z DEBUG: startup: bz2, loaded? No
3062009-07-01T20:59:06Z DEBUG: startup: modplug, loaded? No
3072009-07-01T20:59:06Z DEBUG: startup: rawparse, loaded? No
3082009-07-01T20:59:06Z DEBUG: startup: mythtv, loaded? No
3092009-07-01T20:59:06Z DEBUG: startup: vmnc, loaded? No
3102009-07-01T20:59:06Z DEBUG: startup: stereo, loaded? No
3112009-07-01T20:59:06Z DEBUG: startup: mpegstream, loaded? No
3122009-07-01T20:59:06Z DEBUG: startup: postproc, loaded? No
3132009-07-01T20:59:06Z DEBUG: startup: subenc, loaded? No
3142009-07-01T20:59:06Z DEBUG: startup: y4menc, loaded? No
3152009-07-01T20:59:06Z DEBUG: startup: debug, loaded? No
3162009-07-01T20:59:06Z DEBUG: startup: videobalance, loaded? No
3172009-07-01T20:59:06Z DEBUG: startup: alaw, loaded? No
3182009-07-01T20:59:06Z DEBUG: startup: videomixer, loaded? No
3192009-07-01T20:59:06Z DEBUG: startup: annodex, loaded? No
3202009-07-01T20:59:06Z DEBUG: startup: png, loaded? No
3212009-07-01T20:59:06Z DEBUG: startup: goom, loaded? No
3222009-07-01T20:59:06Z DEBUG: startup: goom2k1, loaded? No
3232009-07-01T20:59:06Z DEBUG: startup: sdl, loaded? No
3242009-07-01T20:59:06Z DEBUG: startup: audiotestsrc, loaded? No
3252009-07-01T20:59:06Z DEBUG: startup: level, loaded? No
3262009-07-01T20:59:06Z DEBUG: startup: matroska, loaded? No
3272009-07-01T20:59:06Z DEBUG: startup: ximagesink, loaded? No
3282009-07-01T20:59:06Z DEBUG: startup: gdkpixbuf, loaded? No
3292009-07-01T20:59:06Z DEBUG: startup: videorate, loaded? No
3302009-07-01T20:59:06Z DEBUG: startup: efence, loaded? No
3312009-07-01T20:59:06Z DEBUG: startup: mulaw, loaded? No
3322009-07-01T20:59:06Z DEBUG: startup: flac, loaded? No
3332009-07-01T20:59:06Z DEBUG: startup: spectrum, loaded? No
3342009-07-01T20:59:06Z DEBUG: startup: audiorate, loaded? No
3352009-07-01T20:59:06Z DEBUG: startup: xvimagesink, loaded? No
3362009-07-01T20:59:06Z DEBUG: startup: auparse, loaded? No
3372009-07-01T20:59:06Z DEBUG: startup: shout2send, loaded? No
3382009-07-01T20:59:06Z DEBUG: startup: rtsp, loaded? No
3392009-07-01T20:59:06Z DEBUG: startup: gio, loaded? No
3402009-07-01T20:59:06Z DEBUG: startup: gdp, loaded? No
3412009-07-01T20:59:06Z DEBUG: startup: equalizer, loaded? No
3422009-07-01T20:59:06Z DEBUG: startup: wavenc, loaded? No
3432009-07-01T20:59:06Z DEBUG: startup: wavpack, loaded? No
3442009-07-01T20:59:06Z DEBUG: startup: videobox, loaded? No
3452009-07-01T20:59:06Z DEBUG: startup: smpte, loaded? No
3462009-07-01T20:59:06Z DEBUG: startup: alphacolor, loaded? No
3472009-07-01T20:59:06Z DEBUG: startup: adder, loaded? No
3482009-07-01T20:59:06Z DEBUG: startup: video4linux, loaded? No
3492009-07-01T20:59:06Z DEBUG: startup: gamma, loaded? No
3502009-07-01T20:59:06Z DEBUG: startup: taglib, loaded? No
3512009-07-01T20:59:06Z DEBUG: startup: cacasink, loaded? No
3522009-07-01T20:59:06Z DEBUG: startup: jpeg, loaded? No
3532009-07-01T20:59:06Z DEBUG: startup: soup, loaded? No
3542009-07-01T20:59:06Z DEBUG: startup: videocrop, loaded? No
3552009-07-01T20:59:06Z DEBUG: startup: videotestsrc, loaded? No
3562009-07-01T20:59:06Z DEBUG: startup: videoflip, loaded? No
3572009-07-01T20:59:06Z DEBUG: startup: speex, loaded? No
3582009-07-01T20:59:06Z DEBUG: startup: cairo, loaded? No
3592009-07-01T20:59:06Z DEBUG: startup: monoscope, loaded? No
3602009-07-01T20:59:06Z DEBUG: startup: alpha, loaded? No
3612009-07-01T20:59:06Z DEBUG: startup: dv, loaded? No
3622009-07-01T20:59:06Z DEBUG: startup: subparse, loaded? No
3632009-07-01T20:59:06Z DEBUG: startup: aasink, loaded? No
3642009-07-01T20:59:06Z DEBUG: startup: halelements, loaded? No
3652009-07-01T20:59:06Z DEBUG: startup: audiofx, loaded? No
3662009-07-01T20:59:06Z DEBUG: startup: rtp, loaded? No
3672009-07-01T20:59:06Z DEBUG: startup: cdparanoia, loaded? No
3682009-07-01T20:59:06Z DEBUG: startup: pango, loaded? No
3692009-07-01T20:59:06Z DEBUG: startup: apetag, loaded? No
3702009-07-01T20:59:06Z DEBUG: startup: ximagesrc, loaded? No
3712009-07-01T20:59:06Z DEBUG: startup: navigationtest, loaded? No
3722009-07-01T20:59:06Z DEBUG: startup: cdio, loaded? No
3732009-07-01T20:59:06Z DEBUG: startup: video4linux2, loaded? No
3742009-07-01T20:59:06Z DEBUG: startup: 1394, loaded? No
3752009-07-01T20:59:06Z DEBUG: startup: flxdec, loaded? No
3762009-07-01T20:59:06Z DEBUG: startup: libvisual, loaded? No
3772009-07-01T20:59:06Z DEBUG: startup: cutter, loaded? No
3782009-07-01T20:59:06Z DEBUG: startup: gconfelements, loaded? No
3792009-07-01T20:59:06Z DEBUG: startup: effectv, loaded? No
3802009-07-01T20:59:06Z DEBUG: startup: staticelements, loaded? Yes
3812009-07-01T20:59:06Z INFO: setStartupState: Startup state changing from (state #12) to STATE_SEED_GRANTED_WAIT
3822009-07-01T20:59:06Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9000
3832009-07-01T20:59:06Z INFO: start: LLEventPollResponder::start <1> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
3842009-07-01T20:59:06Z INFO: setStartupState: Startup state changing from STATE_SEED_GRANTED_WAIT to STATE_SEED_CAP_GRANTED
3852009-07-01T20:59:06Z INFO: idle_startup: Initializing communications...
3862009-07-01T20:59:06Z INFO: importFile: LLCacheName loaded 72 agent names
3872009-07-01T20:59:06Z INFO: importFile: LLCacheName loaded 1 group names
3882009-07-01T20:59:06Z WARNING: createDummyWidget: Making dummy icon named voice_channel_icon in voice_remote
3892009-07-01T20:59:06Z INFO: LLDrawPoolWLSky: loading WindLight cloud noise from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/clouds2.tga
3902009-07-01T20:59:07Z WARNING: LLViewerImage::setIsMissingAsset: /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/skins/default/textures/ <uuid>: Marking image as missing
3912009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_SEED_CAP_GRANTED to STATE_WORLD_WAIT
3922009-07-01T20:59:08Z INFO: idle_startup: viewer: UserLoginLocationReply() Enabling 127.0.0.1:9000 with code <code>
3932009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 243 going past packet end at 243
3942009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 247 going past packet end at 243
3952009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 251 going past packet end at 243
3962009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 252 going past packet end at 243
3972009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 253 going past packet end at 243
3982009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_WORLD_WAIT to STATE_AGENT_SEND
3992009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_AGENT_SEND to STATE_AGENT_WAIT
4002009-07-01T20:59:08Z INFO: stopInternetStream: entered stopInternetStream()
4012009-07-01T20:59:09Z WARNING: process_agent_movement_complete: agent_movement_complete() with NULL avatarp.
4022009-07-01T20:59:09Z INFO: process_agent_movement_complete: Changing home region to 256000:256000
4032009-07-01T20:59:09Z INFO: sendToSim: Sending throttle settings, total BW 1050
4042009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_AGENT_WAIT to STATE_INVENTORY_SEND
4052009-07-01T20:59:09Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/<uuid>.inv)
4062009-07-01T20:59:09Z INFO: loadSkeleton: Successfully loaded 7 categories and 0 items from cache.
4072009-07-01T20:59:09Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/<uuid>.inv)
4082009-07-01T20:59:09Z INFO: loadSkeleton: Successfully loaded 5 categories and 0 items from cache.
4092009-07-01T20:59:09Z INFO: buildParentChildMap: LLInventoryModel::buildParentChildMap()
4102009-07-01T20:59:09Z INFO: idle_startup: Setting Inventory changed mask and notifying observers
4112009-07-01T20:59:09Z INFO: idle_startup: Registering Callbacks
4122009-07-01T20:59:09Z INFO: idle_startup: Inventory
4132009-07-01T20:59:09Z INFO: idle_startup: AvatarTracker
4142009-07-01T20:59:09Z INFO: idle_startup: Landmark
4152009-07-01T20:59:09Z INFO: idle_startup: Requesting Mute List
4162009-07-01T20:59:09Z INFO: idle_startup: Requesting Money Balance
4172009-07-01T20:59:09Z INFO: idle_startup: Requesting Agent Data
4182009-07-01T20:59:09Z INFO: idle_startup: Creating Inventory Views
4192009-07-01T20:59:09Z INFO: init: LLInventoryView::init: reading from 0xbfa919f0
4202009-07-01T20:59:09Z INFO: idle_startup: Inventory Views Created
4212009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_INVENTORY_SEND to STATE_MISC
4222009-07-01T20:59:09Z INFO: initWind: LLAudioEngine_OpenAL::initWind() start
4232009-07-01T20:59:09Z INFO: initWind: LLAudioEngine_OpenAL::initWind() done
4242009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_MISC to STATE_PRECACHE
4252009-07-01T20:59:09Z INFO: idle: Transmitting sessions stats
4262009-07-01T20:59:09Z WARNING: send_stats: Could not get ViewerStats capability
4272009-07-01T20:59:09Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Ooh
4282009-07-01T20:59:09Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Aah
4292009-07-01T20:59:09Z WARNING: buildCharacter: Missing 'Ooh' morph for lipsync, using fallback.
4302009-07-01T20:59:09Z WARNING: buildCharacter: Missing 'Aah' morph for lipsync, using fallback.
4312009-07-01T20:59:09Z INFO: backgroundFetch: Inventory fetch completed
4322009-07-01T20:59:09Z INFO: addCircuitData: LLCircuit::addCircuitData for 127.0.0.1:9002
4332009-07-01T20:59:09Z INFO: addRegion: Adding new region (1000:1001)
4342009-07-01T20:59:09Z INFO: addRegion: Host: 127.0.0.1:9002
4352009-07-01T20:59:09Z INFO: process_enable_simulator: simulator_enable() Enabling 127.0.0.1:9002 with code <code>
4362009-07-01T20:59:09Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS/<uuid>/
4372009-07-01T20:59:09Z INFO: processUseCachedMuteList: LLMuteList::processUseCachedMuteList()
4382009-07-01T20:59:09Z WARNING: loadFromFile: Couldn't open mute list /home/aw/.imprudence/cache/<uuid>.cached_mute
4392009-07-01T20:59:09Z INFO: process_money_balance_reply: L$, credit, committed: 0 0 0
4402009-07-01T20:59:10Z INFO: LLAgent::sendAgentSetAppearance: TAT: Sent AgentSetAppearance: HEAD UPPER LOWER EYES
4412009-07-01T20:59:10Z INFO: LLAgent::sendAgentSetAppearance: TAT: Sending cached texture data
4422009-07-01T20:59:10Z INFO: deleteCachedImages: Clearing Static Textures KB GL:5120KB TGA:326KB
4432009-07-01T20:59:10Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9002
4442009-07-01T20:59:10Z INFO: start: LLEventPollResponder::start <2> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
4452009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 4 bytes at position 243 going past packet end at 243
4462009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 4 bytes at position 247 going past packet end at 243
4472009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 251 going past packet end at 243
4482009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 252 going past packet end at 243
4492009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 253 going past packet end at 243
4502009-07-01T20:59:14Z INFO: idle: Unknown object updates: 3
4512009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_PRECACHE to STATE_WEARABLES_WAIT
4522009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_WEARABLES_WAIT to STATE_CLEANUP
4532009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_CLEANUP to STATE_STARTED
4542009-07-01T20:59:15Z INFO: idle_startup: Doing first audio_update_volume...
4552009-07-01T20:59:15Z INFO: idle_startup: Done first audio_update_volume.
4562009-07-01T20:59:15Z INFO: updateGeometry: WL Skydome strips in 3 batches.
4572009-07-01T20:59:20Z INFO: sendMapLayerRequest: LLWorldMap::sendMapLayerRequest via capability
4582009-07-01T20:59:20Z INFO: backgroundFetch: Inventory fetch completed
4592009-07-01T20:59:20Z INFO: parse: LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:OpenSim.Framework.Communications.Capabilities.LLSDMapLayerResponse
4602009-07-01T20:59:20Z INFO: result: LLMapLayerResponder::result from capabilities
4612009-07-01T20:59:26Z WARNING: onSelectServer: onSelectServer called
4622009-07-01T20:59:31Z WARNING: teleport: tp button current grid = local
4632009-07-01T20:59:31Z INFO: requestLogout: requestLogout
4642009-07-01T20:59:31Z WARNING: send_stats: Could not get ViewerStats capability
4652009-07-01T20:59:31Z INFO: sendLogoutRequest: Created logout marker file /home/aw/.imprudence/logs/Imprudence.logout_marker
4662009-07-01T20:59:31Z INFO: saveSnapshot: Saving snapshot to: /home/aw/.imprudence/armin_weatherwax/screen_last.bmp
4672009-07-01T20:59:32Z INFO: removeRegion: Removing region 256000:256256
4682009-07-01T20:59:32Z INFO: stop: LLEventPollResponder::stop <2> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
4692009-07-01T20:59:32Z INFO: disableCircuit: LLMessageSystem::disableCircuit for 127.0.0.1:9002
4702009-07-01T20:59:32Z WARNING: disableCircuit: Couldn't find circuit code for 127.0.0.1:9002
4712009-07-01T20:59:32Z INFO: stop: LLEventPollResponder::stop <2> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
4722009-07-01T20:59:38Z INFO: forceQuit: Destroying the entire world
4732009-07-01T20:59:38Z INFO: setStartupState: Startup state changing from STATE_STARTED to STATE_LOGIN_SHOW
4742009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named ne_label in mini_mapview
4752009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named nw_label in mini_mapview
4762009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named sw_label in mini_mapview
4772009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named se_label in mini_mapview
4782009-07-01T20:59:38Z INFO: disconnectViewer: Disconnecting viewer!
4792009-07-01T20:59:38Z INFO: saveToFile: LLInventoryModel::saveToFile(/home/aw/.imprudence/cache/<uuid>.inv)
4802009-07-01T20:59:38Z INFO: saveToFile: LLInventoryModel::saveToFile(/home/aw/.imprudence/cache/<uuid>.inv)
4812009-07-01T20:59:38Z INFO: removeRegion: Removing region 256000:256000
4822009-07-01T20:59:38Z INFO: stop: LLEventPollResponder::stop <1> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
4832009-07-01T20:59:38Z INFO: cleanup: Viewer disconnected
4842009-07-01T20:59:38Z INFO: cleanup: Cleaning Up
4852009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0xce9dc20 has 2 refs!
4862009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x9534b040 has 2 refs!
4872009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x95c48ed0 has 2 refs!
4882009-07-01T20:59:38Z INFO: LLAgent::setAvatarObject: Setting LLAgent::mAvatarObject to NULL
4892009-07-01T20:59:38Z WARNING: updateMeshTextures: updateMeshTextures: invalid host for object: <uuid>
4902009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x953a0100 has 2 refs!
4912009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x95855210 has 2 refs!
4922009-07-01T20:59:38Z INFO: cleanup: HUD Objects cleaned up
4932009-07-01T20:59:38Z INFO: LLVoiceClient::stateMachine: Disabling voice before connection to daemon, terminating.
4942009-07-01T20:59:38Z INFO: setStartupState: Startup state changing from STATE_LOGIN_SHOW to STATE_LOGIN_CLEANUP
4952009-07-01T20:59:38Z INFO: idle_startup: Attempting login as: Armin Weatherwax <uuid>
4962009-07-01T20:59:38Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml to load.
4972009-07-01T20:59:38Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml - No settings found.
4982009-07-01T20:59:38Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings.xml to load.
4992009-07-01T20:59:38Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings.xml - No settings found.
5002009-07-01T20:59:38Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/armin_weatherwax/settings_per_account.xml
5012009-07-01T20:59:38Z INFO: loadFile: Loading history.xml file at url_history.xml
5022009-07-01T20:59:38Z INFO: loadFile: file missing, ill-formed, or simply undefined; not changing the file
5032009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_CLEANUP to STATE_LOGIN_AUTH_INIT
5042009-07-01T20:59:39Z INFO: rewriteURI: Rewriting http://127.0.0.1:9000/
5052009-07-01T20:59:39Z INFO: rewriteResult: [0] http://127.0.0.1:9000/
5062009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTH_INIT to STATE_LOGIN_AUTHENTICATE
5072009-07-01T20:59:39Z INFO: authenticate: Authenticating: Armin Weatherwax,
5082009-07-01T20:59:39Z INFO: authenticate: Options: inventory-root, inventory-skeleton, inventory-lib-root, inventory-lib-owner, inventory-skel-lib, initial-outfit, gestures, event_categories, event_notifications, classified_categories, buddy-list, ui-config, tutorial_setting, login-flags, global-textures, END
5092009-07-01T20:59:39Z INFO: authenticate: LLUserAuth::authenticate: uri=http://127.0.0.1:9000/
5102009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTHENTICATE to STATE_LOGIN_NO_DATA_YET
5112009-07-01T20:59:39Z INFO: transferRate: Buffer size: 105394 B
5122009-07-01T20:59:39Z INFO: transferRate: Transfer rate: 5616.14 Kb/s
5132009-07-01T20:59:39Z INFO: authResponse: Processed response: 0
5142009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING
5152009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_DOWNLOADING to STATE_LOGIN_PROCESS_RESPONSE
5162009-07-01T20:59:39Z INFO: saveFile: Saved grids to /home/aw/.imprudence/user_settings/grid_info.xml
5172009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_PROCESS_RESPONSE to STATE_WORLD_INIT
5182009-07-01T20:59:39Z INFO: LLVoiceClient::userAuthorized: name "Armin Weatherwax" , ID <uuid>
5192009-07-01T20:59:39Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
5202009-07-01T20:59:39Z INFO: addRegion: Adding new region (1000:1000)
5212009-07-01T20:59:39Z INFO: addRegion: Host: 127.0.0.1:9000
5222009-07-01T20:59:39Z INFO: idle_startup: Adding initial simulator { 256000, 256000, 0 }
5232009-07-01T20:59:39Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS/<uuid>/
5242009-07-01T20:59:39Z INFO: LLAgent::setRegion: Moving agent into region: located at 127.0.0.1:9000
5252009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_WORLD_INIT to (state #12)
5262009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from (state #12) to STATE_SEED_GRANTED_WAIT
5272009-07-01T20:59:39Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9000
5282009-07-01T20:59:39Z INFO: start: LLEventPollResponder::start <3> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
5292009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_SEED_GRANTED_WAIT to STATE_SEED_CAP_GRANTED
5302009-07-01T20:59:39Z INFO: idle_startup: Initializing communications...
5312009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_SEED_CAP_GRANTED to STATE_WORLD_WAIT
5322009-07-01T20:59:42Z INFO: idle_startup: viewer: UserLoginLocationReply() Enabling 127.0.0.1:9000 with code <code>
5332009-07-01T20:59:42Z INFO: stop: LLEventPollResponder::stop <1> http://127.0.0.1:9000/CAPS/EQG/<uuid>/
5342009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_WORLD_WAIT to STATE_AGENT_SEND
5352009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
5362009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
5372009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
5382009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
5392009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_AGENT_SEND to STATE_AGENT_WAIT
5402009-07-01T20:59:42Z INFO: checkPacketInID: packet_out_of_order - got packet 370 expecting 1424 from 127.0.0.1:9000
5412009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_AGENT_WAIT to STATE_INVENTORY_SEND
5422009-07-01T20:59:42Z INFO: stopInternetStream: entered stopInternetStream()
5432009-07-01T20:59:42Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/<uuid>.inv)
5442009-07-01T20:59:42Z INFO: loadSkeleton: Successfully loaded 7 categories and 0 items from cache.
5452009-07-01T20:59:42Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/<uuid>.inv)
5462009-07-01T20:59:42Z INFO: loadSkeleton: Successfully loaded 5 categories and 0 items from cache.
5472009-07-01T20:59:42Z INFO: buildParentChildMap: LLInventoryModel::buildParentChildMap()
5482009-07-01T20:59:42Z INFO: idle_startup: Setting Inventory changed mask and notifying observers
5492009-07-01T20:59:42Z INFO: idle_startup: Registering Callbacks
5502009-07-01T20:59:42Z INFO: idle_startup: Inventory
5512009-07-01T20:59:42Z INFO: idle_startup: AvatarTracker
5522009-07-01T20:59:42Z INFO: idle_startup: Landmark
5532009-07-01T20:59:42Z INFO: idle_startup: Requesting Mute List
5542009-07-01T20:59:42Z INFO: idle_startup: Requesting Money Balance
5552009-07-01T20:59:42Z INFO: idle_startup: Requesting Agent Data
5562009-07-01T20:59:42Z INFO: idle_startup: Creating Inventory Views
5572009-07-01T20:59:42Z INFO: init: LLInventoryView::init: reading from 0xbfa919f0
5582009-07-01T20:59:42Z INFO: idle_startup: Inventory Views Created
5592009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_INVENTORY_SEND to STATE_MISC
5602009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_MISC to STATE_PRECACHE
5612009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 243 going past packet end at 243
5622009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 247 going past packet end at 243
5632009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 251 going past packet end at 243
5642009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 252 going past packet end at 243
5652009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 253 going past packet end at 243
5662009-07-01T20:59:42Z INFO: checkPacketInID: packet_out_of_order - got packet 3 expecting 371 from 127.0.0.1:9000
5672009-07-01T20:59:42Z WARNING: process_agent_movement_complete: agent_movement_complete() with NULL avatarp.
5682009-07-01T20:59:42Z INFO: process_agent_movement_complete: Changing home region to 256000:256000
5692009-07-01T20:59:42Z INFO: sendToSim: Sending throttle settings, total BW 1050
5702009-07-01T20:59:42Z INFO: backgroundFetch: Inventory fetch completed
5712009-07-01T20:59:42Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Ooh
5722009-07-01T20:59:42Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Aah
5732009-07-01T20:59:42Z WARNING: buildCharacter: Missing 'Ooh' morph for lipsync, using fallback.
5742009-07-01T20:59:42Z WARNING: buildCharacter: Missing 'Aah' morph for lipsync, using fallback.
5752009-07-01T20:59:42Z INFO: do_elfio_glibc_backtrace: Opening stack trace file /home/aw/.imprudence/logs/stack_trace.log
5762009-07-01T20:59:46Z INFO: do_elfio_glibc_backtrace: Finished generating stack trace.
5772009-07-01T20:59:46Z INFO: handleViewerCrash: Handle viewer crash entry.
5782009-07-01T20:59:46Z INFO: handleViewerCrash: Creating crash marker file /home/aw/.imprudence/logs/Imprudence.error_marker
5792009-07-01T20:59:46Z INFO: handleViewerCrash: Created crash marker file /home/aw/.imprudence/logs/Imprudence.error_marker
5802009-07-01T20:59:46Z INFO: handleViewerCrash: Handle viewer crash generating stats log.
5812009-07-01T20:59:46Z INFO: writeDebugInfo: Opening debug file /home/aw/.imprudence/logs/debug_info.log
diff --git a/linden/indra/newview/llworld.cpp b/linden/indra/newview/llworld.cpp
index 9ee789a..4c02191 100644
--- a/linden/indra/newview/llworld.cpp
+++ b/linden/indra/newview/llworld.cpp
@@ -117,6 +117,7 @@ LLWorld::LLWorld() :
117 117
118void LLWorld::destroyClass() 118void LLWorld::destroyClass()
119{ 119{
120 mHoleWaterObjects.clear();
120 gObjectList.destroy(); 121 gObjectList.destroy();
121 for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); ) 122 for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
122 { 123 {
diff --git a/mAttachedObject.diff.txt b/mAttachedObject.diff.txt
new file mode 100644
index 0000000..73ffab5
--- /dev/null
+++ b/mAttachedObject.diff.txt
@@ -0,0 +1,16 @@
1diff --git a/linden/indra/newview/llviewerjointattachment.h b/linden/indra/newview/llviewerjointattachment.h
2index dd63bfd..6a505c0 100644
3--- a/linden/indra/newview/llviewerjointattachment.h
4+++ b/linden/indra/newview/llviewerjointattachment.h
5@@ -98,7 +98,9 @@ protected:
6 void calcLOD();
7
8 protected:
9- LLPointer<LLViewerObject> mAttachedObject;
10+
11+ // Backlink only; don't make this an LLPointer.
12+ LLViewerObject* mAttachedObject;
13 BOOL mVisibleInFirst;
14 LLVector3 mOriginalPos;
15 S32 mGroup;
16
diff --git a/meerkat-llmenugl.diff.txt b/meerkat-llmenugl.diff.txt
new file mode 100644
index 0000000..7ca8c2c
--- /dev/null
+++ b/meerkat-llmenugl.diff.txt
@@ -0,0 +1,534 @@
1diff -uwN /linden/indra/llui/llmenugl.cpp /linden/indra/llui/llmenugl.cpp
2--- /linden/indra/llui/llmenugl.cpp 2009-06-12 14:14:40.000000000 +0200
3+++ /linden/indra/llui/llmenugl.cpp 2009-06-23 02:16:35.000000000 +0200
4@@ -413,7 +413,7 @@
5 LLMenuGL::setKeyboardMode(FALSE);
6
7 doIt();
8- make_ui_sound("UISndClickRelease");
9+ //make_ui_sound("UISndClickRelease");
10 return TRUE;
11 }
12
13@@ -1033,47 +1033,30 @@
14 }
15
16
17-LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle<LLView> branch,
18+LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch,
19 KEY key, MASK mask ) :
20 LLMenuItemGL( name, label, key, mask ),
21 mBranch( branch )
22 {
23- if(!dynamic_cast<LLMenuGL*>(branch.get()))
24- {
25- llerrs << "Non-menu handle passed as branch reference." << llendl;
26- }
27-
28- if(getBranch())
29- {
30- getBranch()->setVisible( FALSE );
31- getBranch()->setParentMenuItem(this);
32- }
33-}
34-
35-LLMenuItemBranchGL::~LLMenuItemBranchGL()
36-{
37- LLView::deleteViewByHandle(mBranch);
38+ mBranch->setVisible( FALSE );
39+ mBranch->setParentMenuItem(this);
40 }
41
42 // virtual
43 LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
44 {
45 // richard: this is redundant with parent, remove
46- if (getBranch())
47+ if (mBranch->getName() == name)
48 {
49- if(getBranch()->getName() == name)
50- {
51- return getBranch();
52+ return mBranch;
53 }
54-
55 // Always recurse on branches
56- LLView* child = getBranch()->getChildView(name, recurse, FALSE);
57- if(child)
58+ LLView* child = mBranch->getChildView(name, recurse, FALSE);
59+ if (!child)
60 {
61- return child;
62+ child = LLView::getChildView(name, recurse, create_if_missing);
63 }
64- }
65- return LLView::getChildView(name, recurse, create_if_missing);;
66+ return child;
67 }
68
69 // virtual
70@@ -1083,25 +1066,21 @@
71 LLMenuGL::setKeyboardMode(FALSE);
72
73 doIt();
74- make_ui_sound("UISndClickRelease");
75+ //make_ui_sound("UISndClickRelease");
76 return TRUE;
77 }
78
79 BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
80 {
81- if(getBranch())
82- {
83- return getBranch()->handleAcceleratorKey(key, mask);
84- }
85- return FALSE;
86+ return mBranch->handleAcceleratorKey(key, mask);
87 }
88
89 // virtual
90 LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const
91 {
92- if (getBranch())
93+ if (mBranch)
94 {
95- return getBranch()->getXML();
96+ return mBranch->getXML();
97 }
98
99 return LLMenuItemGL::getXML();
100@@ -1112,19 +1091,16 @@
101 // if not, it will be added to the list
102 BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp)
103 {
104- if(getBranch())
105- {
106- U32 item_count = getBranch()->getItemCount();
107+ U32 item_count = mBranch->getItemCount();
108 LLMenuItemGL *item;
109
110 while (item_count--)
111 {
112- if ((item = getBranch()->getItem(item_count)))
113+ if ((item = mBranch->getItem(item_count)))
114 {
115 return item->addToAcceleratorList(listp);
116 }
117 }
118- }
119 return FALSE;
120 }
121
122@@ -1146,18 +1122,18 @@
123
124 // keyboard navigation automatically propagates highlight to sub-menu
125 // to facilitate fast menu control via jump keys
126- if (getBranch() && LLMenuGL::getKeyboardMode() && !getBranch()->getHighlightedItem())
127+ if (LLMenuGL::getKeyboardMode() && !mBranch->getHighlightedItem())
128 {
129- getBranch()->highlightNextItem(NULL);
130+ mBranch->highlightNextItem(NULL);
131 }
132 }
133
134 BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
135 {
136 BOOL handled = FALSE;
137- if (called_from_parent && getBranch())
138+ if (called_from_parent)
139 {
140- handled = getBranch()->handleKey(key, mask, called_from_parent);
141+ handled = mBranch->handleKey(key, mask, called_from_parent);
142 }
143
144 if (!handled)
145@@ -1171,9 +1147,9 @@
146 BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
147 {
148 BOOL handled = FALSE;
149- if (called_from_parent && getBranch())
150+ if (called_from_parent)
151 {
152- handled = getBranch()->handleUnicodeChar(uni_char, TRUE);
153+ handled = mBranch->handleUnicodeChar(uni_char, TRUE);
154 }
155
156 if (!handled)
157@@ -1189,19 +1165,14 @@
158 {
159 if (highlight == getHighlight()) return;
160
161- if(!getBranch())
162- {
163- return;
164- }
165-
166- BOOL auto_open = getEnabled() && (!getBranch()->getVisible() || getBranch()->getTornOff());
167+ BOOL auto_open = getEnabled() && (!mBranch->getVisible() || mBranch->getTornOff());
168 // torn off menus don't open sub menus on hover unless they have focus
169 if (getMenu()->getTornOff() && !((LLFloater*)getMenu()->getParent())->hasFocus())
170 {
171 auto_open = FALSE;
172 }
173 // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus)
174- if (getBranch()->getTornOff())
175+ if (mBranch->getTornOff())
176 {
177 auto_open = FALSE;
178 }
179@@ -1215,14 +1186,14 @@
180 }
181 else
182 {
183- if (getBranch()->getTornOff())
184+ if (mBranch->getTornOff())
185 {
186- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
187- getBranch()->clearHoverItem();
188+ ((LLFloater*)mBranch->getParent())->setFocus(FALSE);
189+ mBranch->clearHoverItem();
190 }
191 else
192 {
193- getBranch()->setVisible( FALSE );
194+ mBranch->setVisible( FALSE );
195 }
196 }
197 }
198@@ -1230,7 +1201,7 @@
199 void LLMenuItemBranchGL::draw()
200 {
201 LLMenuItemGL::draw();
202- if (getBranch() && getBranch()->getVisible() && !getBranch()->getTornOff())
203+ if (mBranch->getVisible() && !mBranch->getTornOff())
204 {
205 setHighlight(TRUE);
206 }
207@@ -1238,33 +1209,33 @@
208
209 void LLMenuItemBranchGL::updateBranchParent(LLView* parentp)
210 {
211- if (getBranch() && getBranch()->getParent() == NULL)
212+ if (mBranch->getParent() == NULL)
213 {
214 // make the branch menu a sibling of my parent menu
215- getBranch()->updateParent(parentp);
216+ mBranch->updateParent(parentp);
217 }
218 }
219
220 void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility )
221 {
222- if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff())
223+ if (new_visibility == FALSE && !mBranch->getTornOff())
224 {
225- getBranch()->setVisible(FALSE);
226+ mBranch->setVisible(FALSE);
227 }
228 LLMenuItemGL::onVisibilityChange(new_visibility);
229 }
230
231 BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask )
232 {
233- if (getMenu()->getVisible() && getBranch() && getBranch()->getVisible() && key == KEY_LEFT)
234+ if (getMenu()->getVisible() && mBranch->getVisible() && key == KEY_LEFT)
235 {
236 // switch to keyboard navigation mode
237 LLMenuGL::setKeyboardMode(TRUE);
238
239- BOOL handled = getBranch()->clearHoverItem();
240- if (getBranch()->getTornOff())
241+ BOOL handled = mBranch->clearHoverItem();
242+ if (mBranch->getTornOff())
243 {
244- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
245+ ((LLFloater*)mBranch->getParent())->setFocus(FALSE);
246 }
247 if (handled && getMenu()->getTornOff())
248 {
249@@ -1275,12 +1246,12 @@
250
251 if (getHighlight() &&
252 getMenu()->isOpen() &&
253- key == KEY_RIGHT && getBranch() && !getBranch()->getHighlightedItem())
254+ key == KEY_RIGHT && !mBranch->getHighlightedItem())
255 {
256 // switch to keyboard navigation mode
257 LLMenuGL::setKeyboardMode(TRUE);
258
259- LLMenuItemGL* itemp = getBranch()->highlightNextItem(NULL);
260+ LLMenuItemGL* itemp = mBranch->highlightNextItem(NULL);
261 if (itemp)
262 {
263 return TRUE;
264@@ -1292,39 +1263,37 @@
265
266 void LLMenuItemBranchGL::openMenu()
267 {
268- if(!getBranch()) return;
269-
270- if (getBranch()->getTornOff())
271+ if (mBranch->getTornOff())
272 {
273- gFloaterView->bringToFront((LLFloater*)getBranch()->getParent());
274+ gFloaterView->bringToFront((LLFloater*)mBranch->getParent());
275 // this might not be necessary, as torn off branches don't get focus and hence no highligth
276- getBranch()->highlightNextItem(NULL);
277+ mBranch->highlightNextItem(NULL);
278 }
279- else if( !getBranch()->getVisible() )
280+ else if( !mBranch->getVisible() )
281 {
282 // get valid rectangle for menus
283 const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
284
285- getBranch()->arrange();
286+ mBranch->arrange();
287
288- LLRect rect = getBranch()->getRect();
289+ LLRect rect = mBranch->getRect();
290 // calculate root-view relative position for branch menu
291 S32 left = getRect().mRight;
292 S32 top = getRect().mTop - getRect().mBottom;
293
294- localPointToOtherView(left, top, &left, &top, getBranch()->getParent());
295+ localPointToOtherView(left, top, &left, &top, mBranch->getParent());
296
297 rect.setLeftTopAndSize( left, top,
298 rect.getWidth(), rect.getHeight() );
299
300- if (getBranch()->getCanTearOff())
301+ if (mBranch->getCanTearOff())
302 {
303 rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS);
304 }
305- getBranch()->setRect( rect );
306+ mBranch->setRect( rect );
307 S32 x = 0;
308 S32 y = 0;
309- getBranch()->localPointToOtherView( 0, 0, &x, &y, getBranch()->getParent() );
310+ mBranch->localPointToOtherView( 0, 0, &x, &y, mBranch->getParent() );
311 S32 delta_x = 0;
312 S32 delta_y = 0;
313 if( y < menu_region_rect.mBottom )
314@@ -1338,9 +1307,8 @@
315 // move sub-menu over to left side
316 delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth())));
317 }
318- getBranch()->translate( delta_x, delta_y );
319- getBranch()->setVisible( TRUE );
320- getBranch()->getParent()->sendChildToFront(getBranch());
321+ mBranch->translate( delta_x, delta_y );
322+ mBranch->setVisible( TRUE );
323 }
324 }
325
326@@ -1357,7 +1325,7 @@
327 protected:
328
329 public:
330- LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLHandle<LLView> branch,
331+ LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLMenuGL* branch,
332 KEY key = KEY_NONE, MASK mask = MASK_NONE );
333
334 virtual std::string getType() const { return "menu"; }
335@@ -1390,7 +1358,7 @@
336
337 LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const std::string& name,
338 const std::string& label,
339- LLHandle<LLView> branch,
340+ LLMenuGL* branch,
341 KEY key, MASK mask ) :
342 LLMenuItemBranchGL( name, label, branch, key, mask )
343 {
344@@ -1459,7 +1427,6 @@
345
346 setHighlight(TRUE);
347 branch->setVisible( TRUE );
348- branch->getParent()->sendChildToFront(branch);
349 }
350 }
351 }
352@@ -2288,7 +2255,7 @@
353 mSpilloverMenu->setBackgroundColor( mBackgroundColor );
354 mSpilloverMenu->setCanTearOff(FALSE);
355
356- mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu->getHandle());
357+ mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu);
358 mSpilloverBranch->setFontStyle(LLFontGL::ITALIC);
359 }
360 }
361@@ -2308,6 +2275,9 @@
362 mItems.erase(found_iter);
363 }
364
365+ delete mSpilloverBranch;
366+ mSpilloverBranch = NULL;
367+
368 // pop off spillover items
369 while (mSpilloverMenu->getItemCount())
370 {
371@@ -2318,12 +2288,6 @@
372 mItems.push_back(itemp);
373 addChild(itemp);
374 }
375-
376- // Delete the branch, and since the branch will delete the menu,
377- // set the menu* to null.
378- delete mSpilloverBranch;
379- mSpilloverBranch = NULL;
380- mSpilloverMenu = NULL;
381 }
382 }
383
384@@ -2496,7 +2460,7 @@
385 BOOL success = TRUE;
386
387 LLMenuItemBranchGL* branch = NULL;
388- branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu->getHandle() );
389+ branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu );
390 branch->setJumpKey(menu->getJumpKey());
391 success &= append( branch );
392
393@@ -2994,7 +2958,6 @@
394 }
395 menu->translate( delta_x, delta_y );
396 menu->setVisible( TRUE );
397- menu->getParent()->sendChildToFront(menu);
398 }
399
400 //-----------------------------------------------------------------------------
401@@ -3185,31 +3148,31 @@
402 switch(pieItemIndexFromXY(x, y))
403 {
404 case 0:
405- make_ui_sound("UISndPieMenuSliceHighlight0");
406+ //make_ui_sound("UISndPieMenuSliceHighlight0");
407 break;
408 case 1:
409- make_ui_sound("UISndPieMenuSliceHighlight1");
410+ //make_ui_sound("UISndPieMenuSliceHighlight1");
411 break;
412 case 2:
413- make_ui_sound("UISndPieMenuSliceHighlight2");
414+ //make_ui_sound("UISndPieMenuSliceHighlight2");
415 break;
416 case 3:
417- make_ui_sound("UISndPieMenuSliceHighlight3");
418+ //make_ui_sound("UISndPieMenuSliceHighlight3");
419 break;
420 case 4:
421- make_ui_sound("UISndPieMenuSliceHighlight4");
422+ //make_ui_sound("UISndPieMenuSliceHighlight4");
423 break;
424 case 5:
425- make_ui_sound("UISndPieMenuSliceHighlight5");
426+ //make_ui_sound("UISndPieMenuSliceHighlight5");
427 break;
428 case 6:
429- make_ui_sound("UISndPieMenuSliceHighlight6");
430+ //make_ui_sound("UISndPieMenuSliceHighlight6");
431 break;
432 case 7:
433- make_ui_sound("UISndPieMenuSliceHighlight7");
434+ //make_ui_sound("UISndPieMenuSliceHighlight7");
435 break;
436 default:
437- make_ui_sound("UISndPieMenuSliceHighlight0");
438+ //make_ui_sound("UISndPieMenuSliceHighlight0");
439 break;
440 }
441 }
442@@ -3357,7 +3320,7 @@
443
444 if (mFirstMouseDown)
445 {
446- make_ui_sound("UISndPieMenuAppear");
447+ //make_ui_sound("UISndPieMenuAppear");
448 mFirstMouseDown = FALSE;
449 }
450
451@@ -3730,7 +3693,7 @@
452
453 if (!mFirstMouseDown)
454 {
455- make_ui_sound("UISndPieMenuAppear");
456+ //make_ui_sound("UISndPieMenuAppear");
457 }
458
459 LLView::setVisible(TRUE);
460@@ -3759,7 +3722,7 @@
461 mHoverItem = NULL;
462 }
463
464- make_ui_sound("UISndPieMenuHide");
465+ //make_ui_sound("UISndPieMenuHide");
466
467 mFirstMouseDown = FALSE;
468 mRightMouseDown = FALSE;
469@@ -4105,7 +4068,7 @@
470 BOOL success = TRUE;
471
472 LLMenuItemBranchGL* branch = NULL;
473- branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu->getHandle());
474+ branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu );
475 success &= branch->addToAcceleratorList(&mAccelerators);
476 success &= append( branch );
477 branch->setJumpKey(branch->getJumpKey());
478diff -uwN /linden/indra/llui/llmenugl.h /linden/indra/llui/llmenugl.h
479--- /linden/indra/llui/llmenugl.h 2009-06-12 14:14:40.000000000 +0200
480+++ /linden/indra/llui/llmenugl.h 2009-06-23 02:16:35.000000000 +0200
481@@ -89,7 +89,6 @@
482 static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }
483
484 LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE );
485- virtual ~LLMenuItemGL() {};
486
487 virtual void setValue(const LLSD& value) { setLabel(value.asString()); }
488
489@@ -562,11 +561,8 @@
490 class LLMenuItemBranchGL : public LLMenuItemGL
491 {
492 public:
493- LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle<LLView> branch,
494+ LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch,
495 KEY key = KEY_NONE, MASK mask = MASK_NONE );
496-
497- virtual ~LLMenuItemBranchGL();
498-
499 virtual LLXMLNodePtr getXML(bool save_children = true) const;
500
501 virtual std::string getType() const { return "menu"; }
502@@ -593,11 +589,11 @@
503
504 virtual BOOL handleKeyHere(KEY key, MASK mask);
505
506- virtual BOOL isActive() const { return isOpen() && getBranch()->getHighlightedItem(); }
507+ virtual BOOL isActive() const { return isOpen() && mBranch->getHighlightedItem(); }
508
509- virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); }
510+ virtual BOOL isOpen() const { return mBranch->isOpen(); }
511
512- LLMenuGL *getBranch() const { return (LLMenuGL*)(mBranch.get()); }
513+ LLMenuGL *getBranch() const { return mBranch; }
514
515 virtual void updateBranchParent( LLView* parentp );
516
517@@ -606,14 +602,14 @@
518
519 virtual void draw();
520
521- virtual void setEnabledSubMenus(BOOL enabled) { if(getBranch()) getBranch()->setEnabledSubMenus(enabled); }
522+ virtual void setEnabledSubMenus(BOOL enabled) { mBranch->setEnabledSubMenus(enabled); }
523
524 virtual void openMenu();
525
526 virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
527
528 private:
529- LLHandle<LLView> mBranch;
530+ LLMenuGL* mBranch;
531 }; // end class LLMenuItemBranchGL
532
533
534
diff --git a/meerkat-message.diff.txt b/meerkat-message.diff.txt
new file mode 100644
index 0000000..a0e3ffc
--- /dev/null
+++ b/meerkat-message.diff.txt
@@ -0,0 +1,1319 @@
1diff --git a/linden/indra/llcommon/llstat.cpp b/linden/indra/llcommon/llstat.cpp
2index 31a72e2..74e8bf1 100644
3--- a/linden/indra/llcommon/llstat.cpp
4+++ b/linden/indra/llcommon/llstat.cpp
5@@ -31,288 +31,17 @@
6 #include "linden_common.h"
7
8 #include "llstat.h"
9-#include "lllivefile.h"
10-#include "llerrorcontrol.h"
11 #include "llframetimer.h"
12 #include "timing.h"
13-#include "llsd.h"
14-#include "llsdserialize.h"
15-#include "llstl.h"
16-#include "u64.h"
17
18
19-// statics
20-BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information
21-LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
22-std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
23
24-//------------------------------------------------------------------------
25-// Live config file to trigger stats logging
26-static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd";
27-static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds
28-
29-class LLStatsConfigFile : public LLLiveFile
30-{
31-public:
32- LLStatsConfigFile()
33- : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE),
34- mChanged(false), mStatsp(NULL) { }
35-
36- static std::string filename();
37-
38-protected:
39- /* virtual */ void loadFile();
40-
41-public:
42- void init(LLPerfStats* statsp);
43- static LLStatsConfigFile& instance();
44- // return the singleton stats config file
45-
46- bool mChanged;
47-
48-protected:
49- LLPerfStats* mStatsp;
50-};
51-
52-std::string LLStatsConfigFile::filename()
53-{
54- return STATS_CONFIG_FILE_NAME;
55-}
56-
57-void LLStatsConfigFile::init(LLPerfStats* statsp)
58-{
59- mStatsp = statsp;
60-}
61-
62-LLStatsConfigFile& LLStatsConfigFile::instance()
63-{
64- static LLStatsConfigFile the_file;
65- return the_file;
66-}
67-
68-
69-/* virtual */
70-// Load and parse the stats configuration file
71-void LLStatsConfigFile::loadFile()
72-{
73- if (!mStatsp)
74- {
75- llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl;
76- return;
77- }
78- mChanged = true;
79-
80- LLSD stats_config;
81- {
82- llifstream file(filename().c_str());
83- if (file.is_open())
84- {
85- LLSDSerialize::fromXML(stats_config, file);
86- if (stats_config.isUndefined())
87- {
88- llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl;
89- mStatsp->setReportPerformanceDuration( 0.f );
90- return;
91- }
92- }
93- else
94- { // File went away, turn off stats if it was on
95- if ( mStatsp->frameStatsIsRunning() )
96- {
97- llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl;
98- mStatsp->setReportPerformanceDuration( 0.f );
99- }
100- return;
101- }
102- }
103-
104- F32 duration = 0.f;
105- F32 interval = 0.f;
106-
107- const char * w = "duration";
108- if (stats_config.has(w))
109- {
110- duration = (F32)stats_config[w].asReal();
111- }
112- w = "interval";
113- if (stats_config.has(w))
114- {
115- interval = (F32)stats_config[w].asReal();
116- }
117-
118- mStatsp->setReportPerformanceDuration( duration );
119- mStatsp->setReportPerformanceInterval( interval );
120-
121- if ( duration > 0 )
122- {
123- if ( interval == 0.f )
124- {
125- llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl;
126- }
127- else
128- {
129- llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl;
130- }
131- }
132- else
133- {
134- llinfos << "Performance stats recording turned off" << llendl;
135- }
136-}
137-
138-
139-//------------------------------------------------------------------------
140-
141-LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) :
142- mFrameStatsFileFailure(FALSE),
143- mSkipFirstFrameStats(FALSE),
144- mProcessName(process_name),
145- mProcessPID(process_pid),
146- mReportPerformanceStatInterval(1.f),
147- mReportPerformanceStatEnd(0.0)
148-{ }
149-
150-LLPerfStats::~LLPerfStats()
151-{
152- LLPerfBlock::clearDynamicStats();
153- mFrameStatsFile.close();
154-}
155-
156-void LLPerfStats::init()
157-{
158- // Initialize the stats config file instance.
159- (void) LLStatsConfigFile::instance().init(this);
160- (void) LLStatsConfigFile::instance().checkAndReload();
161-}
162-
163-// Open file for statistics
164-void LLPerfStats::openPerfStatsFile()
165-{
166- if ( !mFrameStatsFile
167- && !mFrameStatsFileFailure )
168- {
169- std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID);
170- mFrameStatsFile.close();
171- mFrameStatsFile.clear();
172- mFrameStatsFile.open(stats_file, llofstream::out);
173- if ( mFrameStatsFile.fail() )
174- {
175- llinfos << "Error opening statistics log file " << stats_file << llendl;
176- mFrameStatsFileFailure = TRUE;
177- }
178- else
179- {
180- LLSD process_info = LLSD::emptyMap();
181- process_info["name"] = mProcessName;
182- process_info["pid"] = (LLSD::Integer) mProcessPID;
183- process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval;
184- // Add process-specific info.
185- addProcessHeaderInfo(process_info);
186-
187- mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl;
188- }
189- }
190-}
191-
192-// Dump out performance metrics over some time interval
193-void LLPerfStats::dumpIntervalPerformanceStats()
194-{
195- // Ensure output file is OK
196- openPerfStatsFile();
197-
198- if ( mFrameStatsFile )
199- {
200- LLSD stats = LLSD::emptyMap();
201-
202- LLStatAccum::TimeScale scale;
203- if ( getReportPerformanceInterval() == 0.f )
204- {
205- scale = LLStatAccum::SCALE_PER_FRAME;
206- }
207- else if ( getReportPerformanceInterval() < 0.5f )
208- {
209- scale = LLStatAccum::SCALE_100MS;
210- }
211- else
212- {
213- scale = LLStatAccum::SCALE_SECOND;
214- }
215-
216- // Write LLSD into log
217- stats["utc_time"] = (LLSD::String) LLError::utcTime();
218- stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch
219- stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount();
220-
221- // Add process-specific frame info.
222- addProcessFrameInfo(stats, scale);
223- LLPerfBlock::addStatsToLLSDandReset( stats, scale );
224-
225- mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl;
226- }
227-}
228-
229-// Set length of performance stat recording
230-void LLPerfStats::setReportPerformanceDuration( F32 seconds )
231-{
232- if ( seconds <= 0.f )
233- {
234- mReportPerformanceStatEnd = 0.0;
235- LLPerfBlock::setStatsEnabled( FALSE );
236- mFrameStatsFile.close();
237- LLPerfBlock::clearDynamicStats();
238- }
239- else
240- {
241- mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
242- // Clear failure flag to try and create the log file once
243- mFrameStatsFileFailure = FALSE;
244- LLPerfBlock::setStatsEnabled( TRUE );
245- mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
246- }
247-}
248-
249-void LLPerfStats::updatePerFrameStats()
250-{
251- (void) LLStatsConfigFile::instance().checkAndReload();
252- static LLFrameTimer performance_stats_timer;
253- if ( frameStatsIsRunning() )
254- {
255- if ( mReportPerformanceStatInterval == 0 )
256- { // Record info every frame
257- if ( mSkipFirstFrameStats )
258- { // Skip the first time - was started this frame
259- mSkipFirstFrameStats = FALSE;
260- }
261- else
262- {
263- dumpIntervalPerformanceStats();
264- }
265- }
266- else
267- {
268- performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() );
269- if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval ))
270- {
271- dumpIntervalPerformanceStats();
272- }
273- }
274-
275- if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd )
276- { // Reached end of time, clear it to stop reporting
277- setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly
278- llinfos << "Recording performance stats completed" << llendl;
279- }
280- }
281-}
282-
283-
284-//------------------------------------------------------------------------
285-
286-U64 LLStatAccum::sScaleTimes[NUM_SCALES] =
287+U64 LLStatAccum::sScaleTimes[IMPL_NUM_SCALES] =
288 {
289 USEC_PER_SEC / 10, // 100 millisec
290 USEC_PER_SEC * 1, // seconds
291 USEC_PER_SEC * 60, // minutes
292+ USEC_PER_SEC * 60 * 2 // two minutes
293 #if ENABLE_LONG_TIME_STATS
294 // enable these when more time scales are desired
295 USEC_PER_SEC * 60*60, // hours
296@@ -342,7 +71,7 @@ void LLStatAccum::reset(U64 when)
297 mRunning = TRUE;
298 mLastTime = when;
299
300- for (int i = 0; i < NUM_SCALES; ++i)
301+ for (int i = 0; i < IMPL_NUM_SCALES; ++i)
302 {
303 mBuckets[i].accum = 0.0;
304 mBuckets[i].endTime = when + sScaleTimes[i];
305@@ -375,7 +104,7 @@ void LLStatAccum::sum(F64 value, U64 when)
306 // how long is this value for
307 U64 timeSpan = when - mLastTime;
308
309- for (int i = 0; i < NUM_SCALES; ++i)
310+ for (int i = 0; i < IMPL_NUM_SCALES; ++i)
311 {
312 Bucket& bucket = mBuckets[i];
313
314@@ -421,12 +150,7 @@ F32 LLStatAccum::meanValue(TimeScale scale) const
315 {
316 return 0.0;
317 }
318- if ( scale == SCALE_PER_FRAME )
319- { // Per-frame not supported here
320- scale = SCALE_100MS;
321- }
322-
323- if (scale < 0 || scale >= NUM_SCALES)
324+ if (scale < 0 || scale >= IMPL_NUM_SCALES)
325 {
326 llwarns << "llStatAccum::meanValue called for unsupported scale: "
327 << scale << llendl;
328@@ -536,15 +260,12 @@ void LLStatMeasure::sample(F64 value)
329
330 // ------------------------------------------------------------------------
331
332-LLStatTime::LLStatTime(const std::string & key)
333- : LLStatAccum(false),
334- mFrameNumber(LLFrameTimer::getFrameCount()),
335- mTotalTimeInFrame(0),
336- mKey(key)
337-#if LL_DEBUG
338- , mRunning(FALSE)
339-#endif
340+LLStatTime::LLStatTime(bool use_frame_timer)
341+ : LLStatAccum(use_frame_timer),
342+ mFrameNumber(0),
343+ mTotalTimeInFrame(0)
344 {
345+ mFrameNumber = LLFrameTimer::getFrameCount();
346 }
347
348 void LLStatTime::start()
349@@ -558,12 +279,6 @@ void LLStatTime::start()
350 }
351
352 sum(0.0);
353-
354-#if LL_DEBUG
355- // Shouldn't be running already
356- llassert( !mRunning );
357- mRunning = TRUE;
358-#endif
359 }
360
361 void LLStatTime::stop()
362@@ -571,149 +286,7 @@ void LLStatTime::stop()
363 U64 end_time = getCurrentUsecs();
364 U64 duration = end_time - mLastTime;
365 sum(F64(duration), end_time);
366- //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl;
367 mTotalTimeInFrame += duration;
368-
369-#if LL_DEBUG
370- mRunning = FALSE;
371-#endif
372-}
373-
374-/* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const
375-{
376- if ( LLStatAccum::SCALE_PER_FRAME == scale )
377- {
378- return mTotalTimeInFrame;
379- }
380- else
381- {
382- return LLStatAccum::meanValue(scale);
383- }
384-}
385-
386-
387-// ------------------------------------------------------------------------
388-
389-
390-// Use this constructor for pre-defined LLStatTime objects
391-LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL)
392-{
393- if (mPredefinedStat)
394- {
395- // If dynamic stats are turned on, this will create a separate entry in the stat map.
396- initDynamicStat(mPredefinedStat->mKey);
397-
398- // Start predefined stats. These stats are not part of the stat map.
399- mPredefinedStat->start();
400- }
401-}
402-
403-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
404-// These are also turned on or off via the switch passed in
405-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
406-{
407- if (!sStatsEnabled) return;
408-
409- if (NULL == key2 || strlen(key2) == 0)
410- {
411- initDynamicStat(key1);
412- }
413- else
414- {
415- std::ostringstream key;
416- key << key1 << "_" << key2;
417- initDynamicStat(key.str());
418- }
419-}
420-
421-void LLPerfBlock::initDynamicStat(const std::string& key)
422-{
423- // Early exit if dynamic stats aren't enabled.
424- if (!sStatsEnabled) return;
425-
426- mLastPath = sCurrentStatPath; // Save and restore current path
427- sCurrentStatPath += "/" + key; // Add key to current path
428-
429- // See if the LLStatTime object already exists
430- stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath);
431- if ( iter == sStatMap.end() )
432- {
433- // StatEntry object doesn't exist, so create it
434- mDynamicStat = new StatEntry( key );
435- sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path
436- }
437- else
438- {
439- // Found this path in the map, use the object there
440- mDynamicStat = (*iter).second; // Get StatEntry for the current path
441- }
442-
443- if (mDynamicStat)
444- {
445- mDynamicStat->mStat.start();
446- mDynamicStat->mCount++;
447- }
448- else
449- {
450- llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl;
451- sCurrentStatPath = mLastPath;
452- }
453-}
454-
455-
456-// Destructor does the time accounting
457-LLPerfBlock::~LLPerfBlock()
458-{
459- if (mPredefinedStat) mPredefinedStat->stop();
460- if (mDynamicStat)
461- {
462- mDynamicStat->mStat.stop();
463- sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block
464- }
465-}
466-
467-
468-// Clear the map of any dynamic stats. Static routine
469-void LLPerfBlock::clearDynamicStats()
470-{
471- std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer());
472- sStatMap.clear();
473-}
474-
475-// static - Extract the stat info into LLSD
476-void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
477- LLStatAccum::TimeScale scale )
478-{
479- // If we aren't in per-frame scale, we need to go from second to microsecond.
480- U32 scale_adjustment = 1;
481- if (LLStatAccum::SCALE_PER_FRAME != scale)
482- {
483- scale_adjustment = USEC_PER_SEC;
484- }
485- stat_map_t::iterator iter = sStatMap.begin();
486- for ( ; iter != sStatMap.end(); ++iter )
487- { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time
488- const std::string & stats_full_path = (*iter).first;
489-
490- StatEntry * stat = (*iter).second;
491- if (stat)
492- {
493- if (stat->mCount > 0)
494- {
495- stats[stats_full_path] = LLSD::emptyMap();
496- stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale));
497- if (stat->mCount > 1)
498- {
499- stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount;
500- }
501- stat->mCount = 0;
502- }
503- }
504- else
505- { // WTF? Shouldn't have a NULL pointer in the map.
506- llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
507- }
508- }
509 }
510
511
512diff --git a/linden/indra/llcommon/llstat.h b/linden/indra/llcommon/llstat.h
513index eceb5e3..0e66cf0 100644
514--- a/linden/indra/llcommon/llstat.h
515+++ b/linden/indra/llcommon/llstat.h
516@@ -33,13 +33,9 @@
517 #define LL_LLSTAT_H
518
519 #include <deque>
520-#include <map>
521
522 #include "lltimer.h"
523 #include "llframetimer.h"
524-#include "llfile.h"
525-
526-class LLSD;
527
528 // Set this if longer stats are needed
529 #define ENABLE_LONG_TIME_STATS 0
530@@ -62,18 +58,19 @@ public:
531 SCALE_100MS,
532 SCALE_SECOND,
533 SCALE_MINUTE,
534+ SCALE_TWO_MINUTE,
535 #if ENABLE_LONG_TIME_STATS
536 SCALE_HOUR,
537 SCALE_DAY,
538 SCALE_WEEK,
539 #endif
540- NUM_SCALES, // Use to size storage arrays
541- SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets
542+ NUM_SCALES
543 };
544
545- static U64 sScaleTimes[NUM_SCALES];
546+ static const TimeScale IMPL_NUM_SCALES = (TimeScale)(SCALE_TWO_MINUTE + 1);
547+ static U64 sScaleTimes[IMPL_NUM_SCALES];
548
549- virtual F32 meanValue(TimeScale scale) const;
550+ F32 meanValue(TimeScale scale) const;
551 // see the subclasses for the specific meaning of value
552
553 F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); }
554@@ -89,8 +86,8 @@ public:
555 // Get current microseconds based on timer type
556
557 BOOL mUseFrameTimer;
558- BOOL mRunning;
559
560+ BOOL mRunning;
561 U64 mLastTime;
562
563 struct Bucket
564@@ -102,7 +99,7 @@ public:
565 F64 lastAccum;
566 };
567
568- Bucket mBuckets[NUM_SCALES];
569+ Bucket mBuckets[IMPL_NUM_SCALES];
570
571 BOOL mLastSampleValid;
572 F64 mLastSampleValue;
573@@ -139,115 +136,37 @@ public:
574 };
575
576
577+class LLTimeBlock;
578+
579 class LLStatTime : public LLStatAccum
580 // gathers statistics about time spent in a block of code
581 // measure average duration per second in the block
582 {
583 public:
584- LLStatTime( const std::string & key = "undefined" );
585+ LLStatTime(bool use_frame_timer = false);
586
587 U32 mFrameNumber; // Current frame number
588 U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame
589
590- void setKey( const std::string & key ) { mKey = key; };
591-
592- virtual F32 meanValue(TimeScale scale) const;
593-
594 private:
595- void start(); // Start and stop measuring time block
596+ void start();
597 void stop();
598-
599- std::string mKey; // Tag representing this time block
600-
601-#if LL_DEBUG
602- BOOL mRunning; // TRUE if start() has been called
603-#endif
604-
605- friend class LLPerfBlock;
606+ friend class LLTimeBlock;
607 };
608
609-// ----------------------------------------------------------------------------
610-
611-
612-// Use this class on the stack to record statistics about an area of code
613-class LLPerfBlock
614+class LLTimeBlock
615 {
616 public:
617- struct StatEntry
618- {
619- StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {}
620- LLStatTime mStat;
621- U32 mCount;
622- };
623- typedef std::map<std::string, StatEntry*> stat_map_t;
624-
625- // Use this constructor for pre-defined LLStatTime objects
626- LLPerfBlock(LLStatTime* stat);
627-
628- // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
629- LLPerfBlock( const char* key1, const char* key2 = NULL);
630-
631-
632- ~LLPerfBlock();
633-
634- static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; };
635- static S32 getStatsEnabled() { return sStatsEnabled; };
636-
637- static void clearDynamicStats(); // Reset maps to clear out dynamic objects
638- static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin
639- LLStatAccum::TimeScale scale );
640-
641+ LLTimeBlock(LLStatTime& stat) : mStat(stat) { mStat.start(); }
642+ ~LLTimeBlock() { mStat.stop(); }
643 private:
644- // Initialize dynamically created LLStatTime objects
645- void initDynamicStat(const std::string& key);
646-
647- std::string mLastPath; // Save sCurrentStatPath when this is called
648- LLStatTime * mPredefinedStat; // LLStatTime object to get data
649- StatEntry * mDynamicStat; // StatEntryobject to get data
650-
651- static BOOL sStatsEnabled; // Normally FALSE
652- static stat_map_t sStatMap; // Map full path string to LLStatTime objects
653- static std::string sCurrentStatPath; // Something like "frame/physics/physics step"
654+ LLStatTime& mStat;
655 };
656
657-// ----------------------------------------------------------------------------
658
659-class LLPerfStats
660-{
661-public:
662- LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
663- virtual ~LLPerfStats();
664-
665- virtual void init(); // Reset and start all stat timers
666- virtual void updatePerFrameStats();
667- // Override these function to add process-specific information to the performance log header and per-frame logging.
668- virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ }
669- virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ }
670-
671- // High-resolution frame stats
672- BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); };
673- F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; };
674- void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; };
675- void setReportPerformanceDuration( F32 seconds );
676- void setProcessName(const std::string& process_name) { mProcessName = process_name; }
677- void setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
678-
679-protected:
680- void openPerfStatsFile(); // Open file for high resolution metrics logging
681- void dumpIntervalPerformanceStats();
682
683- llofstream mFrameStatsFile; // File for per-frame stats
684- BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts
685- BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report
686- std::string mProcessName;
687- S32 mProcessPID;
688
689-private:
690- F32 mReportPerformanceStatInterval; // Seconds between performance stats
691- F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats
692-};
693
694-// ----------------------------------------------------------------------------
695 class LLStat
696 {
697 public:
698diff --git a/linden/indra/llcommon/llstatenums.h b/linden/indra/llcommon/llstatenums.h
699index febd958..ae3be14 100644
700--- a/linden/indra/llcommon/llstatenums.h
701+++ b/linden/indra/llcommon/llstatenums.h
702@@ -33,41 +33,38 @@
703
704 enum
705 {
706- LL_SIM_STAT_TIME_DILATION, // 0
707+ LL_SIM_STAT_TIME_DILATION,
708 LL_SIM_STAT_FPS,
709 LL_SIM_STAT_PHYSFPS,
710 LL_SIM_STAT_AGENTUPS,
711 LL_SIM_STAT_FRAMEMS,
712- LL_SIM_STAT_NETMS, // 5
713+ LL_SIM_STAT_NETMS,
714 LL_SIM_STAT_SIMOTHERMS,
715 LL_SIM_STAT_SIMPHYSICSMS,
716 LL_SIM_STAT_AGENTMS,
717 LL_SIM_STAT_IMAGESMS,
718- LL_SIM_STAT_SCRIPTMS, // 10
719+ LL_SIM_STAT_SCRIPTMS,
720 LL_SIM_STAT_NUMTASKS,
721 LL_SIM_STAT_NUMTASKSACTIVE,
722 LL_SIM_STAT_NUMAGENTMAIN,
723 LL_SIM_STAT_NUMAGENTCHILD,
724- LL_SIM_STAT_NUMSCRIPTSACTIVE, // 15
725+ LL_SIM_STAT_NUMSCRIPTSACTIVE,
726 LL_SIM_STAT_LSLIPS,
727 LL_SIM_STAT_INPPS,
728 LL_SIM_STAT_OUTPPS,
729 LL_SIM_STAT_PENDING_DOWNLOADS,
730- LL_SIM_STAT_PENDING_UPLOADS, // 20
731+ LL_SIM_STAT_PENDING_UPLOADS,
732 LL_SIM_STAT_VIRTUAL_SIZE_KB,
733 LL_SIM_STAT_RESIDENT_SIZE_KB,
734 LL_SIM_STAT_PENDING_LOCAL_UPLOADS,
735 LL_SIM_STAT_TOTAL_UNACKED_BYTES,
736- LL_SIM_STAT_PHYSICS_PINNED_TASKS, // 25
737+ LL_SIM_STAT_PHYSICS_PINNED_TASKS,
738 LL_SIM_STAT_PHYSICS_LOD_TASKS,
739 LL_SIM_STAT_SIMPHYSICSSTEPMS,
740 LL_SIM_STAT_SIMPHYSICSSHAPEMS,
741 LL_SIM_STAT_SIMPHYSICSOTHERMS,
742- LL_SIM_STAT_SIMPHYSICSMEMORY, // 30
743+ LL_SIM_STAT_SIMPHYSICSMEMORY,
744 LL_SIM_STAT_SCRIPT_EPS,
745- LL_SIM_STAT_SIMSPARETIME,
746- LL_SIM_STAT_SIMSLEEPTIME,
747- LL_SIM_STAT_IOPUMPTIME,
748 };
749
750 #endif
751diff --git a/linden/indra/llmessage/lliohttpserver.cpp b/linden/indra/llmessage/lliohttpserver.cpp
752index 167f212..39fecb4 100644
753--- a/linden/indra/llmessage/lliohttpserver.cpp
754+++ b/linden/indra/llmessage/lliohttpserver.cpp
755@@ -47,7 +47,6 @@
756 #include "llpumpio.h"
757 #include "llsd.h"
758 #include "llsdserialize_xml.h"
759-#include "llstat.h"
760 #include "llstl.h"
761 #include "lltimer.h"
762
763@@ -172,26 +171,22 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
764 std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
765 if(verb == HTTP_VERB_GET)
766 {
767- LLPerfBlock getblock("http_get");
768 mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
769 }
770 else if(verb == HTTP_VERB_PUT)
771 {
772- LLPerfBlock putblock("http_put");
773 LLSD input;
774 LLSDSerialize::fromXML(input, istr);
775 mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
776 }
777 else if(verb == HTTP_VERB_POST)
778 {
779- LLPerfBlock postblock("http_post");
780 LLSD input;
781 LLSDSerialize::fromXML(input, istr);
782 mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
783 }
784 else if(verb == HTTP_VERB_DELETE)
785 {
786- LLPerfBlock delblock("http_delete");
787 mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
788 }
789 else if(verb == HTTP_VERB_OPTIONS)
790diff --git a/linden/indra/llmessage/llmessagetemplate.h b/linden/indra/llmessage/llmessagetemplate.h
791index 2390eea..a4062fa 100644
792--- a/linden/indra/llmessage/llmessagetemplate.h
793+++ b/linden/indra/llmessage/llmessagetemplate.h
794@@ -34,8 +34,11 @@
795
796 #include "lldarray.h"
797 #include "message.h" // TODO: babbage: Remove...
798-#include "llstat.h"
799+#include "llmsgvariabletype.h"
800 #include "llstl.h"
801+#include <list>
802+#include <algorithm>
803+#include <functional>
804
805 class LLMsgVarData
806 {
807@@ -270,6 +273,31 @@ enum EMsgDeprecation
808 MD_DEPRECATED
809 };
810
811+class LLMessageTemplateHandlerEntry
812+{
813+public:
814+ LLMessageTemplateHandlerEntry(message_handler_func_t handler, void **userdata = NULL) :
815+ mHandlerFunc(handler), mUserData(userdata) {}
816+
817+ void call(LLMessageSystem *msgsystem) const { mHandlerFunc(msgsystem, mUserData); }
818+
819+ bool operator==(const LLMessageTemplateHandlerEntry&a) { return mHandlerFunc == a.mHandlerFunc; }
820+private:
821+ // message handler function (this is set by each application)
822+ message_handler_func_t mHandlerFunc;
823+ void **mUserData;
824+};
825+
826+class callHandler : public std::unary_function<LLMessageTemplateHandlerEntry, void>
827+{
828+public:
829+ callHandler(LLMessageSystem *msg) : mMsg(msg) {}
830+ void operator()(const LLMessageTemplateHandlerEntry& a) const { a.call(mMsg); }
831+private:
832+ LLMessageSystem *mMsg;
833+};
834+
835+
836 class LLMessageTemplate
837 {
838 public:
839@@ -291,9 +319,10 @@ public:
840 mTotalDecodeTime(0.f),
841 mMaxDecodeTimePerMsg(0.f),
842 mBanFromTrusted(false),
843- mBanFromUntrusted(false),
844- mHandlerFunc(NULL),
845- mUserData(NULL)
846+ //mBanFromUntrusted(false),
847+ //mHandlerFunc(NULL),
848+ //mUserData(NULL)
849+ mBanFromUntrusted(false)
850 {
851 mName = LLMessageStringTable::getInstance()->getString(name);
852 }
853@@ -361,21 +390,91 @@ public:
854 return mDeprecation;
855 }
856
857- void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
858+// void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
859+ /**
860+ * @brief Adds a handler
861+ * This function adds a new handler to be called when the message arrives.
862+ * Repeated additions of the same handler function will be ignored.
863+ * @note delHandlerFunc() must be called to remove the registration
864+ * @param handler Function to call
865+ * @param user_data User specified data to pass to the function
866+ */
867+ void addHandlerFunc(message_handler_func_t handler, void **user_data)
868 {
869- mHandlerFunc = handler_func;
870- mUserData = user_data;
871+ LLMessageTemplateHandlerEntry h(handler, user_data);
872+
873+ if ( std::find(mHandlers.begin(), mHandlers.end(), h ) != mHandlers.end() )
874+ {
875+ return;
876+ }
877+
878+ mHandlers.push_back( h );
879+ }
880+
881+ /**
882+ * @brief Sets a handler
883+ * This function sets a handler to be called when the message arrives.
884+ * Any existing handlers are unregistered.
885+ * @note delHandlerFunc() must be called to remove the registration
886+ * @param handler Function to call
887+ * @param user_data User specified data to pass to the function
888+ */
889+ void setHandlerFunc(message_handler_func_t handler, void **user_data)
890+ {
891+ mHandlers.clear();
892+ if( handler )
893+ {
894+ addHandlerFunc(handler, user_data);
895+ }
896+ else
897+ {
898+ llwarns << "code has reset handler for \"" << mName << "\" by setting it to NULL." << llendl;
899+ }
900+ }
901+
902+ /**
903+ * @brief Removes a handler
904+ * Removes a handler from the list of handlers.
905+ * Attempts to remove handlers that aren't in the list are silently
906+ * ignored.
907+ * @param handler Function to remove
908+ */
909+ void delHandlerFunc(message_handler_func_t handler)
910+ {
911+ //mHandlerFunc = handler_func;
912+ //mUserData = user_data;
913+ mHandlers.remove( LLMessageTemplateHandlerEntry(handler) );
914 }
915
916 BOOL callHandlerFunc(LLMessageSystem *msgsystem) const
917 {
918- if (mHandlerFunc)
919+ //if (mHandlerFunc)
920+ if ( mHandlers.empty() )
921+ {
922+ return FALSE;
923+ }
924+ /*
925+ * Be on the safe side and use for_each only when necessary. There is Linden code ("ReplyPayPrice") that
926+ * does not take the multiple reply handlers into account and simply tries to unregister
927+ * by setting the handler function to 0, unfortunately from within the reply handler so in this case
928+ * the for_each iterator inside std_algo.h is invalidated leading to a crash if the memory is reused
929+ * in between.
930+ */
931+ else if( mHandlers.size() == 1 )
932+ {
933+ //KOW HACK we probably want to re-enable the llPerfBlocks here, may need a vendor merge for llstats.cpp stuff.
934+ //LLPerfBlock msg_cb_time("msg_cb", mName);
935+ //mHandlerFunc(msgsystem, mUserData);
936+ mHandlers.begin()->call(msgsystem);
937+ return TRUE;
938+ }
939+ else
940 {
941- LLPerfBlock msg_cb_time("msg_cb", mName);
942- mHandlerFunc(msgsystem, mUserData);
943+ //LLPerfBlock msg_cb_time("msg_cb", mName);
944+ std::for_each(mHandlers.begin(), mHandlers.end(), callHandler(msgsystem));
945 return TRUE;
946 }
947- return FALSE;
948+ //return FALSE;
949 }
950
951 bool isUdpBanned() const
952@@ -421,8 +520,9 @@ public:
953
954 private:
955 // message handler function (this is set by each application)
956- void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
957- void **mUserData;
958+// void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
959+// void **mUserData;
960+ std::list<LLMessageTemplateHandlerEntry> mHandlers;
961 };
962
963 #endif // LL_LLMESSAGETEMPLATE_H
964diff --git a/linden/indra/llmessage/llpumpio.cpp b/linden/indra/llmessage/llpumpio.cpp
965index 01a43ec..cc9e543 100644
966--- a/linden/indra/llmessage/llpumpio.cpp
967+++ b/linden/indra/llmessage/llpumpio.cpp
968@@ -41,7 +41,6 @@
969 #include "llapr.h"
970 #include "llmemtype.h"
971 #include "llstl.h"
972-#include "llstat.h"
973
974 // These should not be enabled in production, but they can be
975 // intensely useful during development for finding certain kinds of
976@@ -177,8 +176,7 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) :
977 mCurrentPool(NULL),
978 mCurrentPoolReallocCount(0),
979 mChainsMutex(NULL),
980- mCallbackMutex(NULL),
981- mCurrentChain(mRunningChains.end())
982+ mCallbackMutex(NULL)
983 {
984 LLMemType m1(LLMemType::MTYPE_IO_PUMP);
985 initialize(pool);
986@@ -274,10 +272,7 @@ bool LLPumpIO::setTimeoutSeconds(F32 timeout)
987 void LLPumpIO::adjustTimeoutSeconds(F32 delta)
988 {
989 // If no chain is running, bail
990- if(mRunningChains.end() == mCurrentChain)
991- {
992- return;
993- }
994+ if(current_chain_t() == mCurrentChain) return;
995 (*mCurrentChain).adjustTimeoutSeconds(delta);
996 }
997
998@@ -526,10 +521,7 @@ void LLPumpIO::pump(const S32& poll_timeout)
999 //llinfos << "polling" << llendl;
1000 S32 count = 0;
1001 S32 client_id = 0;
1002- {
1003- LLPerfBlock polltime("pump_poll");
1004 apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
1005- }
1006 PUMP_DEBUG;
1007 for(S32 ii = 0; ii < count; ++ii)
1008 {
1009diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp
1010index ccc3d79..0d0ad18 100644
1011--- a/linden/indra/llmessage/message.cpp
1012+++ b/linden/indra/llmessage/message.cpp
1013@@ -754,7 +754,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
1014 clearReceiveState();
1015 valid_packet = FALSE;
1016 }
1017-
1018 if( valid_packet && mTemplateMessageReader->isUdpBanned())
1019 {
1020 llwarns << "Received UDP black listed message "
1021@@ -767,6 +766,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
1022 if( valid_packet )
1023 {
1024 logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
1025+
1026 valid_packet = mTemplateMessageReader->readMessage(buffer, host);
1027 }
1028
1029@@ -2972,7 +2972,7 @@ void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
1030 }
1031
1032
1033-void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
1034+void LLMessageSystem::setHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
1035 {
1036 LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
1037 if (msgtemplate)
1038@@ -2985,6 +2985,32 @@ void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(
1039 }
1040 }
1041
1042+void LLMessageSystem::addHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
1043+{
1044+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
1045+ if (msgtemplate)
1046+ {
1047+ msgtemplate->addHandlerFunc(handler_func, user_data);
1048+ }
1049+ else
1050+ {
1051+ llerrs << name << " is not a known message name!" << llendl;
1052+ }
1053+}
1054+
1055+void LLMessageSystem::delHandlerFuncFast(const char *name, message_handler_func_t handler_func)
1056+{
1057+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
1058+ if (msgtemplate)
1059+ {
1060+ msgtemplate->delHandlerFunc(handler_func);
1061+ }
1062+ else
1063+ {
1064+ llerrs << name << " is not a known message name!" << llendl;
1065+ }
1066+}
1067+
1068 bool LLMessageSystem::callHandler(const char *name,
1069 bool trustedSource, LLMessageSystem* msg)
1070 {
1071@@ -3956,27 +3982,27 @@ void LLMessageSystem::getString(const char *block, const char *var,
1072 blocknum);
1073 }
1074
1075-BOOL LLMessageSystem::has(const char *blockname) const
1076+BOOL LLMessageSystem::has(const char *blockname)
1077 {
1078 return getNumberOfBlocks(blockname) > 0;
1079 }
1080
1081-S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
1082+S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname)
1083 {
1084 return mMessageReader->getNumberOfBlocks(blockname);
1085 }
1086
1087-S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
1088+S32 LLMessageSystem::getNumberOfBlocks(const char *blockname)
1089 {
1090 return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
1091 }
1092
1093-S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
1094+S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname)
1095 {
1096 return mMessageReader->getSize(blockname, varname);
1097 }
1098
1099-S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
1100+S32 LLMessageSystem::getSize(const char *blockname, const char *varname)
1101 {
1102 return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
1103 LLMessageStringTable::getInstance()->getString(varname));
1104@@ -3984,13 +4010,13 @@ S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
1105
1106 // size in bytes of variable length data
1107 S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
1108- const char *varname) const
1109+ const char *varname)
1110 {
1111 return mMessageReader->getSize(blockname, blocknum, varname);
1112 }
1113
1114 S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
1115- const char *varname) const
1116+ const char *varname)
1117 {
1118 return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
1119 LLMessageStringTable::getInstance()->getString(varname));
1120diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h
1121index c503a58..4b96526 100644
1122--- a/linden/indra/llmessage/message.h
1123+++ b/linden/indra/llmessage/message.h
1124@@ -179,7 +179,7 @@ enum EMessageException
1125 MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
1126 };
1127 typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
1128-
1129+typedef void (*message_handler_func_t)(LLMessageSystem *msgsystem, void **user_data);
1130
1131 // message data pieces are used to collect the data called for by the message template
1132 class LLMsgData;
1133@@ -299,12 +299,24 @@ public:
1134
1135
1136 // methods for building, sending, receiving, and handling messages
1137- void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
1138- void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
1139+ void setHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
1140+ void setHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
1141 {
1142 setHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
1143 }
1144
1145+ void addHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
1146+ void addHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
1147+ {
1148+ addHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
1149+ }
1150+
1151+ void delHandlerFuncFast(const char *name, message_handler_func_t);
1152+ void delHandlerFunc(const char *name, message_handler_func_t handler_func)
1153+ {
1154+ delHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func);
1155+ }
1156+
1157 // Set a callback function for a message system exception.
1158 void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
1159 // Call the specified exception func, and return TRUE if a
1160@@ -594,14 +606,14 @@ public:
1161 LLHost findHost(const U32 circuit_code);
1162 void sanityCheck();
1163
1164- BOOL has(const char *blockname) const;
1165- S32 getNumberOfBlocksFast(const char *blockname) const;
1166- S32 getNumberOfBlocks(const char *blockname) const;
1167- S32 getSizeFast(const char *blockname, const char *varname) const;
1168- S32 getSize(const char *blockname, const char *varname) const;
1169+ BOOL has(const char *blockname);
1170+ S32 getNumberOfBlocksFast(const char *blockname);
1171+ S32 getNumberOfBlocks(const char *blockname);
1172+ S32 getSizeFast(const char *blockname, const char *varname);
1173+ S32 getSize(const char *blockname, const char *varname);
1174 S32 getSizeFast(const char *blockname, S32 blocknum,
1175- const char *varname) const; // size in bytes of data
1176- S32 getSize(const char *blockname, S32 blocknum, const char *varname) const;
1177+ const char *varname); // size in bytes of data
1178+ S32 getSize(const char *blockname, S32 blocknum, const char *varname);
1179
1180 void resetReceiveCounts(); // resets receive counts for all message types to 0
1181 void dumpReceiveCounts(); // dumps receive count for each message type to llinfos
1182diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
1183index cf9a7cd..4927571 100644
1184--- a/linden/indra/newview/app_settings/settings.xml
1185+++ b/linden/indra/newview/app_settings/settings.xml
1186@@ -4762,7 +4762,7 @@
1187 <key>Type</key>
1188 <string>U32</string>
1189 <key>Value</key>
1190- <integer>0</integer>
1191+ <integer>1</integer>
1192 </map>
1193 <key>MemoryLogFrequency</key>
1194 <map>
1195diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
1196index cab9815..5cd2a56 100644
1197--- a/linden/indra/newview/llstartup.cpp
1198+++ b/linden/indra/newview/llstartup.cpp
1199@@ -3152,7 +3152,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
1200 msg->setHandlerFunc("ParcelDwellReply",
1201 LLViewerParcelMgr::processParcelDwellReply);
1202
1203- msg->setHandlerFunc("AvatarPropertiesReply",
1204+ msg->addHandlerFunc("AvatarPropertiesReply",
1205 LLPanelAvatar::processAvatarPropertiesReply);
1206 msg->setHandlerFunc("AvatarInterestsReply",
1207 LLPanelAvatar::processAvatarInterestsReply);
1208diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
1209index 03114f7..b984687 100644
1210--- a/linden/indra/newview/llviewermessage.cpp
1211+++ b/linden/indra/newview/llviewermessage.cpp
1212@@ -3516,15 +3516,6 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
1213 case LL_SIM_STAT_SIMPHYSICSMEMORY:
1214 LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value);
1215 break;
1216- case LL_SIM_STAT_SIMSPARETIME:
1217- LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value);
1218- break;
1219- case LL_SIM_STAT_SIMSLEEPTIME:
1220- LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value);
1221- break;
1222- case LL_SIM_STAT_IOPUMPTIME:
1223- LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value);
1224- break;
1225 default:
1226 // Used to be a commented out warning.
1227 LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL;
1228diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h
1229index dc529cd..ebb46b9 100644
1230--- a/linden/indra/newview/llviewerobject.h
1231+++ b/linden/indra/newview/llviewerobject.h
1232@@ -600,7 +600,9 @@ protected:
1233 // extra data sent from the sim...currently only used for tree species info
1234 U8* mData;
1235
1236+public:
1237 LLPointer<LLViewerPartSourceScript> mPartSourcep; // Particle source associated with this object.
1238+protected:
1239 LLAudioSourceVO* mAudioSourcep;
1240 F32 mAudioGain;
1241
1242diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp
1243index 3d2523e..86993df 100644
1244--- a/linden/indra/newview/llvoavatar.cpp
1245+++ b/linden/indra/newview/llvoavatar.cpp
1246@@ -891,7 +891,6 @@ LLVOAvatar::LLVOAvatar(
1247 mEyeBallLeftMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
1248 mEyeBallRightMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
1249 mEyeBallRightMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
1250-
1251 //-------------------------------------------------------------------------
1252 // register motions
1253 //-------------------------------------------------------------------------
1254@@ -960,7 +959,8 @@ LLVOAvatar::LLVOAvatar(
1255 //VTPause(); // VTune
1256
1257 mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
1258- mCurrentGesticulationLevel = 0;
1259+ mCurrentGesticulationLevel = 0;
1260+
1261 }
1262
1263 //------------------------------------------------------------------------
1264@@ -1990,7 +1990,8 @@ void LLVOAvatar::buildCharacter()
1265 mWristRightp = (LLViewerJoint*)mRoot.findJoint("mWristRight");
1266 mEyeLeftp = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
1267 mEyeRightp = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
1268-
1269+
1270+ lldebugs << " initialized joint pointers" << llendl;
1271 //-------------------------------------------------------------------------
1272 // Make sure "well known" pointers exist
1273 //-------------------------------------------------------------------------
1274@@ -2016,7 +2017,7 @@ void LLVOAvatar::buildCharacter()
1275 llerrs << "Failed to create avatar." << llendl;
1276 return;
1277 }
1278-
1279+ lldebugs << "pointers exist, good." << llendl;
1280 //-------------------------------------------------------------------------
1281 // initialize the pelvis
1282 //-------------------------------------------------------------------------
1283@@ -2140,7 +2141,7 @@ void LLVOAvatar::buildCharacter()
1284 }
1285 }
1286 }
1287-
1288+ lldebugs << "builded the attach and detach menus" << llendl;
1289 // add screen attachments
1290 for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
1291 iter != mAttachmentPoints.end(); )
1292@@ -2159,6 +2160,7 @@ void LLVOAvatar::buildCharacter()
1293 &handle_detach_from_avatar, object_attached, attachment));
1294 }
1295 }
1296+ lldebugs << "added screen attachments" << llendl;
1297
1298 for (S32 pass = 0; pass < 2; pass++)
1299 {
1300@@ -2188,6 +2190,7 @@ void LLVOAvatar::buildCharacter()
1301 gDetachSubMenu->appendSeparator();
1302 }
1303 }
1304+ lldebugs << "added other attachments" << llendl;
1305
1306 for (S32 group = 0; group < 8; group++)
1307 {
1308@@ -2241,9 +2244,11 @@ void LLVOAvatar::buildCharacter()
1309 }
1310 }
1311 }
1312+ lldebugs << "added pies" << llendl;
1313 }
1314
1315 mMeshValid = TRUE;
1316+ lldebugs << "mMeshValid = TRUE" << llendl;
1317 }
1318
1319
diff --git a/meerkat-pipeline.cpp.diff.txt b/meerkat-pipeline.cpp.diff.txt
new file mode 100644
index 0000000..b34cd94
--- /dev/null
+++ b/meerkat-pipeline.cpp.diff.txt
@@ -0,0 +1,22 @@
1--- /linden/indra/newview/pipeline.cpp 2009-06-25 15:23:44.000000000 +0200
2+++ /linden/indra/newview/pipeline.cpp 2009-06-25 23:49:51.000000000 +0200
3@@ -2691,7 +2711,10 @@
4 // from Medium -> Low, because we unload all the shaders and the
5 // draw pools aren't aware. I don't know if this has to be a separate
6 // loop before actual rendering. JC
7- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
8+
9+ // TODO: this is a useful fix, find out why it breaks logout -- RMS
10+
11+/* for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
12 {
13 LLDrawPool *poolp = *iter;
14 if (poolp->isFacePool() && hasRenderType(poolp->getType()))
15@@ -2699,6 +2722,7 @@
16 poolp->prerender();
17 }
18 }
19+*/
20 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
21 {
22 LLDrawPool *poolp = *iter;
diff --git a/meerkat-voice.diff.txt b/meerkat-voice.diff.txt
new file mode 100644
index 0000000..f49d511
--- /dev/null
+++ b/meerkat-voice.diff.txt
@@ -0,0 +1,7282 @@
1diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp
2index bf1f678..41137b4 100644
3--- a/linden/indra/newview/llfloaterfriends.cpp
4+++ b/linden/indra/newview/llfloaterfriends.cpp
5@@ -57,7 +57,6 @@
6 #include "llviewermessage.h"
7 #include "lltimer.h"
8 #include "lltextbox.h"
9-#include "llvoiceclient.h"
10
11 //Maximum number of people you can select to do an operation on at once.
12 #define MAX_FRIEND_SELECT 20
13@@ -65,8 +64,6 @@
14 #define RIGHTS_CHANGE_TIMEOUT 5.0
15 #define OBSERVER_TIMEOUT 0.5
16
17-#define ONLINE_SIP_ICON_NAME "slim_icon_16_viewer.tga"
18-
19 // simple class to observe the calling cards.
20 class LLLocalFriendsObserver : public LLFriendObserver, public LLEventTimer
21 {
22@@ -114,14 +111,10 @@ LLPanelFriends::LLPanelFriends() :
23 mEventTimer.stop();
24 mObserver = new LLLocalFriendsObserver(this);
25 LLAvatarTracker::instance().addObserver(mObserver);
26- // For notification when SIP online status changes.
27- LLVoiceClient::getInstance()->addObserver(mObserver);
28 }
29
30 LLPanelFriends::~LLPanelFriends()
31 {
32- // For notification when SIP online status changes.
33- LLVoiceClient::getInstance()->removeObserver(mObserver);
34 LLAvatarTracker::instance().removeObserver(mObserver);
35 delete mObserver;
36 }
37@@ -219,9 +212,7 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
38 LLAvatarTracker& at = LLAvatarTracker::instance();
39 const LLRelationship* relationInfo = at.getBuddyInfo(agent_id);
40 if(!relationInfo) return FALSE;
41-
42- bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(agent_id);
43- bool isOnline = relationInfo->isOnline();
44+ BOOL online = relationInfo->isOnline();
45
46 std::string fullname;
47 BOOL have_name = gCacheName->getFullName(agent_id, fullname);
48@@ -237,17 +228,12 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
49 LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS];
50 online_status_column["column"] = "icon_online_status";
51 online_status_column["type"] = "icon";
52-
53- if (isOnline)
54+
55+ if (online)
56 {
57 friend_column["font-style"] = "BOLD";
58 online_status_column["value"] = "icon_avatar_online.tga";
59 }
60- else if(isOnlineSIP)
61- {
62- friend_column["font-style"] = "BOLD";
63- online_status_column["value"] = ONLINE_SIP_ICON_NAME;
64- }
65
66 LLSD& online_column = element["columns"][LIST_VISIBLE_ONLINE];
67 online_column["column"] = "icon_visible_online";
68@@ -285,30 +271,14 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh
69 if (!info) return FALSE;
70 LLScrollListItem* itemp = mFriendsList->getItem(agent_id);
71 if (!itemp) return FALSE;
72-
73- bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(itemp->getUUID());
74- bool isOnline = info->isOnline();
75
76 std::string fullname;
77 BOOL have_name = gCacheName->getFullName(agent_id, fullname);
78-
79- // Name of the status icon to use
80- std::string statusIcon;
81-
82- if(isOnline)
83- {
84- statusIcon = "icon_avatar_online.tga";
85- }
86- else if(isOnlineSIP)
87- {
88- statusIcon = ONLINE_SIP_ICON_NAME;
89- }
90
91- itemp->getColumn(LIST_ONLINE_STATUS)->setValue(statusIcon);
92-
93+ itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? std::string("icon_avatar_online.tga") : LLStringUtil::null);
94 itemp->getColumn(LIST_FRIEND_NAME)->setValue(fullname);
95 // render name of online friends in bold text
96- ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle((isOnline || isOnlineSIP) ? LLFontGL::BOLD : LLFontGL::NORMAL);
97+ ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL);
98 itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
99 itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION));
100 itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS));
101diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp
102index f30ae8c..d3139ad 100644
103--- a/linden/indra/newview/llimpanel.cpp
104+++ b/linden/indra/newview/llimpanel.cpp
105@@ -49,7 +49,6 @@
106 #include "llconsole.h"
107 #include "llfloater.h"
108 #include "llfloatergroupinfo.h"
109-#include "llfloaterchatterbox.h"
110 #include "llimview.h"
111 #include "llinventory.h"
112 #include "llinventorymodel.h"
113@@ -69,6 +68,7 @@
114 #include "lluictrlfactory.h"
115 #include "llviewerwindow.h"
116 #include "lllogchat.h"
117+#include "llfloaterhtml.h"
118 #include "llweb.h"
119 #include "llhttpclient.h"
120 #include "llmutelist.h"
121@@ -357,7 +357,7 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess
122 llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
123 }
124
125- LLVoiceClient::getInstance()->addObserver(this);
126+ LLVoiceClient::getInstance()->addStatusObserver(this);
127 }
128
129 LLVoiceChannel::~LLVoiceChannel()
130@@ -365,7 +365,7 @@ LLVoiceChannel::~LLVoiceChannel()
131 // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
132 if(gVoiceClient)
133 {
134- gVoiceClient->removeObserver(this);
135+ gVoiceClient->removeStatusObserver(this);
136 }
137
138 sVoiceChannelMap.erase(mSessionID);
139@@ -983,8 +983,7 @@ void LLVoiceChannelP2P::activate()
140 // otherwise answering the call
141 else
142 {
143- LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
144-
145+ LLVoiceClient::getInstance()->answerInvite(mSessionHandle, mOtherUserID);
146 // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
147 mSessionHandle.clear();
148 }
149@@ -1001,7 +1000,7 @@ void LLVoiceChannelP2P::getChannelInfo()
150 }
151
152 // receiving session from other user who initiated call
153-void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
154+void LLVoiceChannelP2P::setSessionHandle(const std::string& handle)
155 {
156 BOOL needs_activate = FALSE;
157 if (callStarted())
158@@ -1024,17 +1023,8 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s
159 }
160
161 mSessionHandle = handle;
162-
163 // The URI of a p2p session should always be the other end's SIP URI.
164- if(!inURI.empty())
165- {
166- setURI(inURI);
167- }
168- else
169- {
170- setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
171- }
172-
173+ setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
174 mReceivedCall = TRUE;
175
176 if (needs_activate)
177@@ -1171,7 +1161,6 @@ void LLFloaterIMPanel::init(const std::string& session_label)
178 FALSE);
179
180 setTitle(mSessionLabel);
181-
182 mInputEditor->setMaxTextLength(1023);
183 // enable line history support for instant message bar
184 mInputEditor->setEnableLineHistory(TRUE);
185@@ -1218,23 +1207,7 @@ LLFloaterIMPanel::~LLFloaterIMPanel()
186 {
187 delete mSpeakers;
188 mSpeakers = NULL;
189-
190- // End the text IM session if necessary
191- if(gVoiceClient && mOtherParticipantUUID.notNull())
192- {
193- switch(mDialog)
194- {
195- case IM_NOTHING_SPECIAL:
196- case IM_SESSION_P2P_INVITE:
197- gVoiceClient->endUserIMSession(mOtherParticipantUUID);
198- break;
199-
200- default:
201- // Appease the compiler
202- break;
203- }
204- }
205-
206+
207 //kicks you out of the voice channel if it is currently active
208
209 // 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).
210@@ -1424,7 +1397,6 @@ void LLFloaterIMPanel::draw()
211 childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
212 childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
213 }
214-
215 LLFloater::draw();
216 }
217
218@@ -1505,7 +1477,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
219 if (!hostp->isFloaterFlashing(this))
220 {
221 hostp->setFloaterFlashing(this, TRUE);
222- LLFloaterChatterBox::markAsUnread(true);
223+//awfixme LLFloaterChatterBox::markAsUnread(true);
224 }
225
226 //// Only increment the number of unread IMs if they're from individuals
227@@ -1585,7 +1557,7 @@ void LLFloaterIMPanel::setVisible(BOOL b)
228 if (hostp->isFloaterFlashing(this))
229 {
230 hostp->setFloaterFlashing(this, FALSE);
231- LLFloaterChatterBox::markAsUnread(false);
232+//awfixme LLFloaterChatterBox::markAsUnread(false);
233
234 /* Don't change containing floater title - leave it "Instant Message" JC
235 LLUIString title = sTitleString;
236@@ -1926,46 +1898,34 @@ void deliver_message(const std::string& utf8_text,
237 EInstantMessage dialog)
238 {
239 std::string name;
240- bool sent = false;
241 gAgent.buildFullname(name);
242
243 const LLRelationship* info = NULL;
244 info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
245-
246 U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
247-
248- if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
249- {
250- // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
251- sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
252- }
253-
254- if(!sent)
255- {
256- // Send message normally.
257
258- // default to IM_SESSION_SEND unless it's nothing special - in
259- // which case it's probably an IM to everyone.
260- U8 new_dialog = dialog;
261+ // default to IM_SESSION_SEND unless it's nothing special - in
262+ // which case it's probably an IM to everyone.
263+ U8 new_dialog = dialog;
264
265- if ( dialog != IM_NOTHING_SPECIAL )
266- {
267- new_dialog = IM_SESSION_SEND;
268- }
269- pack_instant_message(
270- gMessageSystem,
271- gAgent.getID(),
272- FALSE,
273- gAgent.getSessionID(),
274- other_participant_id,
275- name.c_str(),
276- utf8_text.c_str(),
277- offline,
278- (EInstantMessage)new_dialog,
279- im_session_id);
280- gAgent.sendReliableMessage();
281+ if ( dialog != IM_NOTHING_SPECIAL )
282+ {
283+ new_dialog = IM_SESSION_SEND;
284 }
285
286+ pack_instant_message(
287+ gMessageSystem,
288+ gAgent.getID(),
289+ FALSE,
290+ gAgent.getSessionID(),
291+ other_participant_id,
292+ name,
293+ utf8_text,
294+ offline,
295+ (EInstantMessage)new_dialog,
296+ im_session_id);
297+ gAgent.sendReliableMessage();
298+
299 // If there is a mute list and this is not a group chat...
300 if ( LLMuteList::getInstance() )
301 {
302diff --git a/linden/indra/newview/llimpanel.h b/linden/indra/newview/llimpanel.h
303index 0f9c0f3..afec6db 100644
304--- a/linden/indra/newview/llimpanel.h
305+++ b/linden/indra/newview/llimpanel.h
306@@ -161,7 +161,7 @@ public:
307 /*virtual*/ void activate();
308 /*virtual*/ void getChannelInfo();
309
310- void setSessionHandle(const std::string& handle, const std::string &inURI);
311+ void setSessionHandle(const std::string& handle);
312
313 protected:
314 virtual void setState(EState state);
315@@ -295,6 +295,8 @@ private:
316
317 void sendTypingState(BOOL typing);
318
319+ static LLFloaterIMPanel* sInstance;
320+
321 private:
322 LLLineEditor* mInputEditor;
323 LLViewerTextEditor* mHistoryEditor;
324diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp
325index 1072b21..80c6d1c 100644
326--- a/linden/indra/newview/llimview.cpp
327+++ b/linden/indra/newview/llimview.cpp
328@@ -267,8 +267,7 @@ public:
329 EInstantMessage type,
330 EInvitationType inv_type,
331 const std::string& session_handle,
332- const std::string& notify_box,
333- const std::string& session_uri) :
334+ const std::string& notify_box) :
335 mSessionID(session_id),
336 mSessionName(session_name),
337 mCallerID(caller_id),
338@@ -276,8 +275,7 @@ public:
339 mType(type),
340 mInvType(inv_type),
341 mSessionHandle(session_handle),
342- mNotifyBox(notify_box),
343- mSessionURI(session_uri)
344+ mNotifyBox(notify_box)
345 {};
346
347 LLUUID mSessionID;
348@@ -288,7 +286,6 @@ public:
349 EInvitationType mInvType;
350 std::string mSessionHandle;
351 std::string mNotifyBox;
352- std::string mSessionURI;
353 };
354
355
356@@ -579,8 +576,7 @@ BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
357
358 LLUUID LLIMMgr::addP2PSession(const std::string& name,
359 const LLUUID& other_participant_id,
360- const std::string& voice_session_handle,
361- const std::string& caller_uri)
362+ const std::string& voice_session_handle)
363 {
364 LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
365
366@@ -588,7 +584,7 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
367 if(floater)
368 {
369 LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel();
370- voice_channelp->setSessionHandle(voice_session_handle, caller_uri);
371+ voice_channelp->setSessionHandle(voice_session_handle);
372 }
373
374 return session_id;
375@@ -711,8 +707,7 @@ void LLIMMgr::inviteToSession(
376 const std::string& caller_name,
377 EInstantMessage type,
378 EInvitationType inv_type,
379- const std::string& session_handle,
380- const std::string& session_uri)
381+ const std::string& session_handle)
382 {
383 //ignore invites from muted residents
384 if (LLMuteList::getInstance()->isMuted(caller_id))
385@@ -754,8 +749,7 @@ void LLIMMgr::inviteToSession(
386 type,
387 inv_type,
388 session_handle,
389- notify_box_type,
390- session_uri);
391+ notify_box_type);
392
393 LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
394 if (channelp && channelp->callStarted())
395@@ -930,8 +924,7 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
396 invitep->mSessionID = gIMMgr->addP2PSession(
397 invitep->mSessionName,
398 invitep->mCallerID,
399- invitep->mSessionHandle,
400- invitep->mSessionURI );
401+ invitep->mSessionHandle);
402
403 LLFloaterIMPanel* im_floater =
404 gIMMgr->findFloaterBySession(
405diff --git a/linden/indra/newview/llimview.h b/linden/indra/newview/llimview.h
406index cccd6b4..cde95b5 100644
407--- a/linden/indra/newview/llimview.h
408+++ b/linden/indra/newview/llimview.h
409@@ -97,8 +97,7 @@ public:
410 // Creates a P2P session with the requisite handle for responding to voice calls
411 LLUUID addP2PSession(const std::string& name,
412 const LLUUID& other_participant_id,
413- const std::string& voice_session_handle,
414- const std::string& caller_uri = LLStringUtil::null);
415+ const std::string& voice_session_handle);
416
417 // This removes the panel referenced by the uuid, and then
418 // restores internal consistency. The internal pointer is not
419@@ -112,8 +111,7 @@ public:
420 const std::string& caller_name,
421 EInstantMessage type,
422 EInvitationType inv_type,
423- const std::string& session_handle = LLStringUtil::null,
424- const std::string& session_uri = LLStringUtil::null);
425+ const std::string& session_handle = LLStringUtil::null);
426
427 //Updates a given session's session IDs. Does not open,
428 //create or do anything new. If the old session doesn't
429diff --git a/linden/indra/newview/llvoiceclient.cpp b/linden/indra/newview/llvoiceclient.cpp
430index 76ef87d..881beb7 100644
431--- a/linden/indra/newview/llvoiceclient.cpp
432+++ b/linden/indra/newview/llvoiceclient.cpp
433@@ -1,3 +1,4 @@
434+
435 /**
436 * @file llvoiceclient.cpp
437 * @brief Implementation of LLVoiceClient class which is the interface to the voice client process.
438@@ -62,20 +63,15 @@
439 #include "llviewerwindow.h"
440 #include "llviewercamera.h"
441
442-#include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel
443-#include "llfloaterchat.h" // for LLFloaterChat::addChat()
444-
445 // for base64 decoding
446 #include "apr_base64.h"
447
448 // for SHA1 hash
449 #include "apr_sha1.h"
450
451-// for MD5 hash
452-#include "llmd5.h"
453-
454-#define USE_SESSION_GROUPS 0
455-
456+// If we are connecting to agni AND the user's last name is "Linden", join this channel instead of looking up the sim name.
457+// If we are connecting to agni and the user's last name is NOT "Linden", disable voice.
458+#define AGNI_LINDENS_ONLY_CHANNEL "SL"
459 static bool sConnectingToAgni = false;
460 F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
461
462@@ -95,44 +91,6 @@ const F32 UPDATE_THROTTLE_SECONDS = 0.1f;
463 const F32 LOGIN_RETRY_SECONDS = 10.0f;
464 const int MAX_LOGIN_RETRIES = 12;
465
466-static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str)
467-{
468- LLMD5 md5_uuid;
469- md5_uuid.update((const unsigned char*)str.data(), str.size());
470- md5_uuid.finalize();
471- md5_uuid.raw_digest(uuid.mData);
472-}
473-
474-static int scale_mic_volume(float volume)
475-{
476- // incoming volume has the range [0.0 ... 2.0], with 1.0 as the default.
477- // Map it as follows: 0.0 -> 40, 1.0 -> 44, 2.0 -> 75
478-
479- volume -= 1.0f; // offset volume to the range [-1.0 ... 1.0], with 0 at the default.
480- int scaled_volume = 44; // offset scaled_volume by its default level
481- if(volume < 0.0f)
482- scaled_volume += ((int)(volume * 4.0f)); // (44 - 40)
483- else
484- scaled_volume += ((int)(volume * 31.0f)); // (75 - 44)
485-
486- return scaled_volume;
487-}
488-
489-static int scale_speaker_volume(float volume)
490-{
491- // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
492- // Map it as follows: 0.0 -> 0, 0.5 -> 62, 1.0 -> 75
493-
494- volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
495- int scaled_volume = 62; // offset scaled_volume by its default level
496- if(volume < 0.0f)
497- scaled_volume += ((int)(volume * 124.0f)); // (62 - 0) * 2
498- else
499- scaled_volume += ((int)(volume * 26.0f)); // (75 - 62) * 2
500-
501- return scaled_volume;
502-}
503-
504 class LLViewerVoiceAccountProvisionResponder :
505 public LLHTTPClient::Responder
506 {
507@@ -146,13 +104,12 @@ public:
508 {
509 if ( mRetries > 0 )
510 {
511- LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
512 if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision(
513 mRetries - 1);
514 }
515 else
516 {
517- LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
518+ //TODO: throw an error message?
519 if ( gVoiceClient ) gVoiceClient->giveUp();
520 }
521 }
522@@ -161,23 +118,9 @@ public:
523 {
524 if ( gVoiceClient )
525 {
526- std::string voice_sip_uri_hostname;
527- std::string voice_account_server_uri;
528-
529- LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
530-
531- if(content.has("voice_sip_uri_hostname"))
532- voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
533-
534- // this key is actually misnamed -- it will be an entire URI, not just a hostname.
535- if(content.has("voice_account_server_name"))
536- voice_account_server_uri = content["voice_account_server_name"].asString();
537-
538 gVoiceClient->login(
539 content["username"].asString(),
540- content["password"].asString(),
541- voice_sip_uri_hostname,
542- voice_account_server_uri);
543+ content["password"].asString());
544 }
545 }
546
547@@ -224,27 +167,21 @@ protected:
548 int ignoreDepth;
549
550 // Members for processing responses. The values are transient and only valid within a call to processResponse().
551- bool squelchDebugOutput;
552 int returnCode;
553 int statusCode;
554 std::string statusString;
555- std::string requestId;
556+ std::string uuidString;
557 std::string actionString;
558 std::string connectorHandle;
559- std::string versionID;
560 std::string accountHandle;
561 std::string sessionHandle;
562- std::string sessionGroupHandle;
563- std::string alias;
564- std::string applicationString;
565+ std::string eventSessionHandle;
566
567 // Members for processing events. The values are transient and only valid within a call to processResponse().
568 std::string eventTypeString;
569 int state;
570 std::string uriString;
571 bool isChannel;
572- bool incoming;
573- bool enabled;
574 std::string nameString;
575 std::string audioMediaString;
576 std::string displayNameString;
577@@ -254,21 +191,6 @@ protected:
578 bool isSpeaking;
579 int volume;
580 F32 energy;
581- std::string messageHeader;
582- std::string messageBody;
583- std::string notificationType;
584- bool hasText;
585- bool hasAudio;
586- bool hasVideo;
587- bool terminated;
588- std::string blockMask;
589- std::string presenceOnly;
590- std::string autoAcceptMask;
591- std::string autoAddAsBuddy;
592- int numberOfAliases;
593- std::string subscriptionHandle;
594- std::string subscriptionType;
595-
596
597 // Members for processing text between tags
598 std::string textBuffer;
599@@ -301,6 +223,8 @@ void LLVivoxProtocolParser::reset()
600 responseDepth = 0;
601 ignoringTags = false;
602 accumulateText = false;
603+ textBuffer.clear();
604+
605 energy = 0.f;
606 ignoreDepth = 0;
607 isChannel = false;
608@@ -309,15 +233,10 @@ void LLVivoxProtocolParser::reset()
609 isModeratorMuted = false;
610 isSpeaking = false;
611 participantType = 0;
612- squelchDebugOutput = false;
613- returnCode = -1;
614+ returnCode = 0;
615 state = 0;
616 statusCode = 0;
617 volume = 0;
618- textBuffer.clear();
619- alias.clear();
620- numberOfAliases = 0;
621- applicationString.clear();
622 }
623
624 //virtual
625@@ -344,11 +263,33 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
626 mInput.append(buf, istr.gcount());
627 }
628
629+ // MBW -- XXX -- This should no longer be necessary. Or even possible.
630+ // We've read all the data out of the buffer. Make sure it doesn't accumulate.
631+// buffer->clear();
632+
633 // Look for input delimiter(s) in the input buffer. If one is found, send the message to the xml parser.
634 int start = 0;
635 int delim;
636 while((delim = mInput.find("\n\n\n", start)) != std::string::npos)
637 {
638+ // Turn this on to log incoming XML
639+ if(0)
640+ {
641+ int foo = mInput.find("Set3DPosition", start);
642+ int bar = mInput.find("ParticipantPropertiesEvent", start);
643+ if(foo != std::string::npos && (foo < delim))
644+ {
645+ // This is a Set3DPosition response. Don't print it, since these are way too spammy.
646+ }
647+ else if(bar != std::string::npos && (bar < delim))
648+ {
649+ // This is a ParticipantPropertiesEvent response. Don't print it, since these are way too spammy.
650+ }
651+ else
652+ {
653+ LL_INFOS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
654+ }
655+ }
656
657 // Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser)
658 reset();
659@@ -359,21 +300,15 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
660 XML_SetUserData(parser, this);
661 XML_Parse(parser, mInput.data() + start, delim - start, false);
662
663- // If this message isn't set to be squelched, output the raw XML received.
664- if(!squelchDebugOutput)
665- {
666- LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
667- }
668-
669 start = delim + 3;
670 }
671
672 if(start != 0)
673 mInput = mInput.substr(start);
674
675- LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL;
676-
677- if(!gVoiceClient->mConnected)
678+ LL_DEBUGS("Voice") << "at end, mInput is: " << mInput << LL_ENDL;
679+
680+ if((!gVoiceClient)||((gVoiceClient)&&(!gVoiceClient->mConnected)))
681 {
682 // If voice has been disabled, we just want to close the socket. This does so.
683 LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL;
684@@ -426,9 +361,9 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
685
686 if (responseDepth == 0)
687 {
688- isEvent = !stricmp("Event", tag);
689+ isEvent = strcmp("Event", tag) == 0;
690
691- if (!stricmp("Response", tag) || isEvent)
692+ if (strcmp("Response", tag) == 0 || isEvent)
693 {
694 // Grab the attributes
695 while (*attr)
696@@ -436,62 +371,49 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
697 const char *key = *attr++;
698 const char *value = *attr++;
699
700- if (!stricmp("requestId", key))
701+ if (strcmp("requestId", key) == 0)
702 {
703- requestId = value;
704+ uuidString = value;
705 }
706- else if (!stricmp("action", key))
707+ else if (strcmp("action", key) == 0)
708 {
709 actionString = value;
710 }
711- else if (!stricmp("type", key))
712+ else if (strcmp("type", key) == 0)
713 {
714 eventTypeString = value;
715 }
716 }
717 }
718- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
719+ LL_DEBUGS("Voice") << tag << " (" << responseDepth << ")" << LL_ENDL;
720 }
721 else
722 {
723 if (ignoringTags)
724 {
725- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
726+ LL_DEBUGS("Voice") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
727 }
728 else
729 {
730- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
731+ LL_DEBUGS("Voice") << tag << " (" << responseDepth << ")" << LL_ENDL;
732
733 // Ignore the InputXml stuff so we don't get confused
734- if (!stricmp("InputXml", tag))
735+ if (strcmp("InputXml", tag) == 0)
736 {
737 ignoringTags = true;
738 ignoreDepth = responseDepth;
739 accumulateText = false;
740
741- LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
742+ LL_DEBUGS("Voice") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
743 }
744- else if (!stricmp("CaptureDevices", tag))
745+ else if (strcmp("CaptureDevices", tag) == 0)
746 {
747 gVoiceClient->clearCaptureDevices();
748 }
749- else if (!stricmp("RenderDevices", tag))
750+ else if (strcmp("RenderDevices", tag) == 0)
751 {
752 gVoiceClient->clearRenderDevices();
753 }
754- else if (!stricmp("Buddies", tag))
755- {
756- gVoiceClient->deleteAllBuddies();
757- }
758- else if (!stricmp("BlockRules", tag))
759- {
760- gVoiceClient->deleteAllBlockRules();
761- }
762- else if (!stricmp("AutoAcceptRules", tag))
763- {
764- gVoiceClient->deleteAllAutoAcceptRules();
765- }
766-
767 }
768 }
769 responseDepth++;
770@@ -510,138 +432,90 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
771 {
772 if (ignoreDepth == responseDepth)
773 {
774- LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL;
775+ LL_DEBUGS("Voice") << "end of ignore" << LL_ENDL;
776 ignoringTags = false;
777 }
778 else
779 {
780- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
781+ LL_DEBUGS("Voice") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
782 }
783 }
784
785 if (!ignoringTags)
786 {
787- LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
788+ LL_DEBUGS("Voice") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
789
790 // Closing a tag. Finalize the text we've accumulated and reset
791- if (!stricmp("ReturnCode", tag))
792+ if (strcmp("ReturnCode", tag) == 0)
793 returnCode = strtol(string.c_str(), NULL, 10);
794- else if (!stricmp("SessionHandle", tag))
795- sessionHandle = string;
796- else if (!stricmp("SessionGroupHandle", tag))
797- sessionGroupHandle = string;
798- else if (!stricmp("StatusCode", tag))
799+ else if (strcmp("StatusCode", tag) == 0)
800 statusCode = strtol(string.c_str(), NULL, 10);
801- else if (!stricmp("StatusString", tag))
802- statusString = string;
803- else if (!stricmp("ParticipantURI", tag))
804- uriString = string;
805- else if (!stricmp("Volume", tag))
806- volume = strtol(string.c_str(), NULL, 10);
807- else if (!stricmp("Energy", tag))
808- energy = (F32)strtod(string.c_str(), NULL);
809- else if (!stricmp("IsModeratorMuted", tag))
810- isModeratorMuted = !stricmp(string.c_str(), "true");
811- else if (!stricmp("IsSpeaking", tag))
812- isSpeaking = !stricmp(string.c_str(), "true");
813- else if (!stricmp("Alias", tag))
814- alias = string;
815- else if (!stricmp("NumberOfAliases", tag))
816- numberOfAliases = strtol(string.c_str(), NULL, 10);
817- else if (!stricmp("Application", tag))
818- applicationString = string;
819- else if (!stricmp("ConnectorHandle", tag))
820+ else if (strcmp("ConnectorHandle", tag) == 0)
821 connectorHandle = string;
822- else if (!stricmp("VersionID", tag))
823- versionID = string;
824- else if (!stricmp("AccountHandle", tag))
825+ else if (strcmp("AccountHandle", tag) == 0)
826 accountHandle = string;
827- else if (!stricmp("State", tag))
828+ else if (strcmp("SessionHandle", tag) == 0)
829+ {
830+ if (isEvent)
831+ eventSessionHandle = string;
832+ else
833+ sessionHandle = string;
834+ }
835+ else if (strcmp("StatusString", tag) == 0)
836+ statusString = string;
837+ else if (strcmp("State", tag) == 0)
838 state = strtol(string.c_str(), NULL, 10);
839- else if (!stricmp("URI", tag))
840+ else if (strcmp("URI", tag) == 0)
841 uriString = string;
842- else if (!stricmp("IsChannel", tag))
843- isChannel = !stricmp(string.c_str(), "true");
844- else if (!stricmp("Incoming", tag))
845- incoming = !stricmp(string.c_str(), "true");
846- else if (!stricmp("Enabled", tag))
847- enabled = !stricmp(string.c_str(), "true");
848- else if (!stricmp("Name", tag))
849+ else if (strcmp("IsChannel", tag) == 0)
850+ isChannel = string == "true" ? true : false;
851+ else if (strcmp("Name", tag) == 0)
852 nameString = string;
853- else if (!stricmp("AudioMedia", tag))
854+ else if (strcmp("AudioMedia", tag) == 0)
855 audioMediaString = string;
856- else if (!stricmp("ChannelName", tag))
857+ else if (strcmp("ChannelName", tag) == 0)
858 nameString = string;
859- else if (!stricmp("DisplayName", tag))
860+ else if (strcmp("ParticipantURI", tag) == 0)
861+ uriString = string;
862+ else if (strcmp("DisplayName", tag) == 0)
863 displayNameString = string;
864- else if (!stricmp("AccountName", tag))
865+ else if (strcmp("AccountName", tag) == 0)
866 nameString = string;
867- else if (!stricmp("ParticipantType", tag))
868+ else if (strcmp("ParticipantTyppe", tag) == 0)
869 participantType = strtol(string.c_str(), NULL, 10);
870- else if (!stricmp("IsLocallyMuted", tag))
871- isLocallyMuted = !stricmp(string.c_str(), "true");
872- else if (!stricmp("MicEnergy", tag))
873+ else if (strcmp("IsLocallyMuted", tag) == 0)
874+ isLocallyMuted = string == "true" ? true : false;
875+ else if (strcmp("IsModeratorMuted", tag) == 0)
876+ isModeratorMuted = string == "true" ? true : false;
877+ else if (strcmp("IsSpeaking", tag) == 0)
878+ isSpeaking = string == "true" ? true : false;
879+ else if (strcmp("Volume", tag) == 0)
880+ volume = strtol(string.c_str(), NULL, 10);
881+ else if (strcmp("Energy", tag) == 0)
882 energy = (F32)strtod(string.c_str(), NULL);
883- else if (!stricmp("ChannelName", tag))
884+ else if (strcmp("MicEnergy", tag) == 0)
885+ energy = (F32)strtod(string.c_str(), NULL);
886+ else if (strcmp("ChannelName", tag) == 0)
887 nameString = string;
888- else if (!stricmp("ChannelURI", tag))
889- uriString = string;
890- else if (!stricmp("BuddyURI", tag))
891+ else if (strcmp("ChannelURI", tag) == 0)
892 uriString = string;
893- else if (!stricmp("Presence", tag))
894- statusString = string;
895- else if (!stricmp("Device", tag))
896+ else if (strcmp("ChannelListResult", tag) == 0)
897+ {
898+ gVoiceClient->addChannelMapEntry(nameString, uriString);
899+ }
900+ else if (strcmp("Device", tag) == 0)
901 {
902 // This closing tag shouldn't clear the accumulated text.
903 clearbuffer = false;
904 }
905- else if (!stricmp("CaptureDevice", tag))
906+ else if (strcmp("CaptureDevice", tag) == 0)
907 {
908 gVoiceClient->addCaptureDevice(textBuffer);
909 }
910- else if (!stricmp("RenderDevice", tag))
911+ else if (strcmp("RenderDevice", tag) == 0)
912 {
913 gVoiceClient->addRenderDevice(textBuffer);
914 }
915- else if (!stricmp("Buddy", tag))
916- {
917- gVoiceClient->processBuddyListEntry(uriString, displayNameString);
918- }
919- else if (!stricmp("BlockRule", tag))
920- {
921- gVoiceClient->addBlockRule(blockMask, presenceOnly);
922- }
923- else if (!stricmp("BlockMask", tag))
924- blockMask = string;
925- else if (!stricmp("PresenceOnly", tag))
926- presenceOnly = string;
927- else if (!stricmp("AutoAcceptRule", tag))
928- {
929- gVoiceClient->addAutoAcceptRule(autoAcceptMask, autoAddAsBuddy);
930- }
931- else if (!stricmp("AutoAcceptMask", tag))
932- autoAcceptMask = string;
933- else if (!stricmp("AutoAddAsBuddy", tag))
934- autoAddAsBuddy = string;
935- else if (!stricmp("MessageHeader", tag))
936- messageHeader = string;
937- else if (!stricmp("MessageBody", tag))
938- messageBody = string;
939- else if (!stricmp("NotificationType", tag))
940- notificationType = string;
941- else if (!stricmp("HasText", tag))
942- hasText = !stricmp(string.c_str(), "true");
943- else if (!stricmp("HasAudio", tag))
944- hasAudio = !stricmp(string.c_str(), "true");
945- else if (!stricmp("HasVideo", tag))
946- hasVideo = !stricmp(string.c_str(), "true");
947- else if (!stricmp("Terminated", tag))
948- terminated = !stricmp(string.c_str(), "true");
949- else if (!stricmp("SubscriptionHandle", tag))
950- subscriptionHandle = string;
951- else if (!stricmp("SubscriptionType", tag))
952- subscriptionType = string;
953-
954
955 if(clearbuffer)
956 {
957@@ -676,296 +550,147 @@ void LLVivoxProtocolParser::CharData(const char *buffer, int length)
958
959 void LLVivoxProtocolParser::processResponse(std::string tag)
960 {
961- LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL;
962+ LL_DEBUGS("Voice") << tag << LL_ENDL;
963+
964+ if (!gVoiceClient)
965+ return;
966
967- // SLIM SDK: the SDK now returns a statusCode of "200" (OK) for success. This is a change vs. previous SDKs.
968- // According to Mike S., "The actual API convention is that responses with return codes of 0 are successful, regardless of the status code returned",
969- // so I believe this will give correct behavior.
970-
971- if(returnCode == 0)
972- statusCode = 0;
973-
974 if (isEvent)
975 {
976- const char *eventTypeCstr = eventTypeString.c_str();
977- if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
978+ if (eventTypeString == "LoginStateChangeEvent")
979 {
980- gVoiceClient->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state);
981+ gVoiceClient->loginStateChangeEvent(accountHandle, statusCode, statusString, state);
982 }
983- else if (!stricmp(eventTypeCstr, "SessionAddedEvent"))
984- {
985- /*
986- <Event type="SessionAddedEvent">
987- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
988- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
989- <Uri>sip:confctl-1408789@bhr.vivox.com</Uri>
990- <IsChannel>true</IsChannel>
991- <Incoming>false</Incoming>
992- <ChannelName />
993- </Event>
994- */
995- gVoiceClient->sessionAddedEvent(uriString, alias, sessionHandle, sessionGroupHandle, isChannel, incoming, nameString, applicationString);
996- }
997- else if (!stricmp(eventTypeCstr, "SessionRemovedEvent"))
998- {
999- gVoiceClient->sessionRemovedEvent(sessionHandle, sessionGroupHandle);
1000- }
1001- else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent"))
1002- {
1003- gVoiceClient->sessionGroupAddedEvent(sessionGroupHandle);
1004- }
1005- else if (!stricmp(eventTypeCstr, "MediaStreamUpdatedEvent"))
1006- {
1007- /*
1008- <Event type="MediaStreamUpdatedEvent">
1009- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
1010- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
1011- <StatusCode>200</StatusCode>
1012- <StatusString>OK</StatusString>
1013- <State>2</State>
1014- <Incoming>false</Incoming>
1015- </Event>
1016- */
1017- gVoiceClient->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming);
1018- }
1019- else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent"))
1020+ else if (eventTypeString == "SessionNewEvent")
1021 {
1022- /*
1023- <Event type="TextStreamUpdatedEvent">
1024- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg1</SessionGroupHandle>
1025- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==1</SessionHandle>
1026- <Enabled>true</Enabled>
1027- <State>1</State>
1028- <Incoming>true</Incoming>
1029- </Event>
1030- */
1031- gVoiceClient->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming);
1032+ gVoiceClient->sessionNewEvent(accountHandle, eventSessionHandle, state, nameString, uriString);
1033 }
1034- else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent"))
1035+ else if (eventTypeString == "SessionStateChangeEvent")
1036 {
1037- /*
1038- <Event type="ParticipantAddedEvent">
1039- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
1040- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
1041- <ParticipantUri>sip:xI5auBZ60SJWIk606-1JGRQ==@bhr.vivox.com</ParticipantUri>
1042- <AccountName>xI5auBZ60SJWIk606-1JGRQ==</AccountName>
1043- <DisplayName />
1044- <ParticipantType>0</ParticipantType>
1045- </Event>
1046- */
1047- gVoiceClient->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
1048+ gVoiceClient->sessionStateChangeEvent(uriString, statusCode, statusString, eventSessionHandle, state, isChannel, nameString);
1049 }
1050- else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
1051+ else if (eventTypeString == "ParticipantStateChangeEvent")
1052 {
1053- /*
1054- <Event type="ParticipantRemovedEvent">
1055- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4</SessionGroupHandle>
1056- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==4</SessionHandle>
1057- <ParticipantUri>sip:xtx7YNV-3SGiG7rA1fo5Ndw==@bhr.vivox.com</ParticipantUri>
1058- <AccountName>xtx7YNV-3SGiG7rA1fo5Ndw==</AccountName>
1059- </Event>
1060- */
1061- gVoiceClient->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
1062- }
1063- else if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
1064- {
1065- /*
1066- <Event type="ParticipantUpdatedEvent">
1067- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
1068- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
1069- <ParticipantUri>sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com</ParticipantUri>
1070- <IsModeratorMuted>false</IsModeratorMuted>
1071- <IsSpeaking>true</IsSpeaking>
1072- <Volume>44</Volume>
1073- <Energy>0.0879437</Energy>
1074- </Event>
1075- */
1076+ gVoiceClient->participantStateChangeEvent(uriString, statusCode, statusString, state, nameString, displayNameString, participantType);
1077
1078- // These happen so often that logging them is pretty useless.
1079- squelchDebugOutput = true;
1080-
1081- gVoiceClient->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
1082- }
1083- else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))
1084- {
1085- gVoiceClient->auxAudioPropertiesEvent(energy);
1086- }
1087- else if (!stricmp(eventTypeCstr, "BuddyPresenceEvent"))
1088- {
1089- gVoiceClient->buddyPresenceEvent(uriString, alias, statusString, applicationString);
1090- }
1091- else if (!stricmp(eventTypeCstr, "BuddyAndGroupListChangedEvent"))
1092- {
1093- // The buddy list was updated during parsing.
1094- // Need to recheck against the friends list.
1095- gVoiceClient->buddyListChanged();
1096- }
1097- else if (!stricmp(eventTypeCstr, "BuddyChangedEvent"))
1098- {
1099- /*
1100- <Event type="BuddyChangedEvent">
1101- <AccountHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==</AccountHandle>
1102- <BuddyURI>sip:x9fFHFZjOTN6OESF1DUPrZQ==@bhr.vivox.com</BuddyURI>
1103- <DisplayName>Monroe Tester</DisplayName>
1104- <BuddyData />
1105- <GroupID>0</GroupID>
1106- <ChangeType>Set</ChangeType>
1107- </Event>
1108- */
1109- // TODO: Question: Do we need to process this at all?
1110- }
1111- else if (!stricmp(eventTypeCstr, "MessageEvent"))
1112- {
1113- gVoiceClient->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString);
1114 }
1115- else if (!stricmp(eventTypeCstr, "SessionNotificationEvent"))
1116+ else if (eventTypeString == "ParticipantPropertiesEvent")
1117 {
1118- gVoiceClient->sessionNotificationEvent(sessionHandle, uriString, notificationType);
1119+ gVoiceClient->participantPropertiesEvent(uriString, statusCode, statusString, isLocallyMuted, isModeratorMuted, isSpeaking, volume, energy);
1120 }
1121- else if (!stricmp(eventTypeCstr, "SubscriptionEvent"))
1122+ else if (eventTypeString == "AuxAudioPropertiesEvent")
1123 {
1124- gVoiceClient->subscriptionEvent(uriString, subscriptionHandle, alias, displayNameString, applicationString, subscriptionType);
1125- }
1126- else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))
1127- {
1128- /*
1129- <Event type="SessionUpdatedEvent">
1130- <SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
1131- <SessionHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==0</SessionHandle>
1132- <Uri>sip:confctl-9@bhd.vivox.com</Uri>
1133- <IsMuted>0</IsMuted>
1134- <Volume>50</Volume>
1135- <TransmitEnabled>1</TransmitEnabled>
1136- <IsFocused>0</IsFocused>
1137- <SpeakerPosition><Position><X>0</X><Y>0</Y><Z>0</Z></Position></SpeakerPosition>
1138- <SessionFontID>0</SessionFontID>
1139- </Event>
1140- */
1141- // We don't need to process this, but we also shouldn't warn on it, since that confuses people.
1142- }
1143- else
1144- {
1145- LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
1146+ gVoiceClient->auxAudioPropertiesEvent(energy);
1147 }
1148 }
1149 else
1150 {
1151- const char *actionCstr = actionString.c_str();
1152- if (!stricmp(actionCstr, "Connector.Create.1"))
1153+ if (actionString == "Connector.Create.1")
1154 {
1155- gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID);
1156+ gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle);
1157 }
1158- else if (!stricmp(actionCstr, "Account.Login.1"))
1159+ else if (actionString == "Account.Login.1")
1160 {
1161- gVoiceClient->loginResponse(statusCode, statusString, accountHandle, numberOfAliases);
1162+ gVoiceClient->loginResponse(statusCode, statusString, accountHandle);
1163 }
1164- else if (!stricmp(actionCstr, "Session.Create.1"))
1165+ else if (actionString == "Session.Create.1")
1166 {
1167- gVoiceClient->sessionCreateResponse(requestId, statusCode, statusString, sessionHandle);
1168+ gVoiceClient->sessionCreateResponse(statusCode, statusString, sessionHandle);
1169 }
1170- else if (!stricmp(actionCstr, "SessionGroup.AddSession.1"))
1171+ else if (actionString == "Session.Connect.1")
1172 {
1173- gVoiceClient->sessionGroupAddSessionResponse(requestId, statusCode, statusString, sessionHandle);
1174+ gVoiceClient->sessionConnectResponse(statusCode, statusString);
1175 }
1176- else if (!stricmp(actionCstr, "Session.Connect.1"))
1177+ else if (actionString == "Session.Terminate.1")
1178 {
1179- gVoiceClient->sessionConnectResponse(requestId, statusCode, statusString);
1180+ gVoiceClient->sessionTerminateResponse(statusCode, statusString);
1181 }
1182- else if (!stricmp(actionCstr, "Account.Logout.1"))
1183+ else if (actionString == "Account.Logout.1")
1184 {
1185 gVoiceClient->logoutResponse(statusCode, statusString);
1186 }
1187- else if (!stricmp(actionCstr, "Connector.InitiateShutdown.1"))
1188+ else if (actionString == "Connector.InitiateShutdown.1")
1189 {
1190 gVoiceClient->connectorShutdownResponse(statusCode, statusString);
1191 }
1192- else if (!stricmp(actionCstr, "Account.ListBlockRules.1"))
1193- {
1194- gVoiceClient->accountListBlockRulesResponse(statusCode, statusString);
1195- }
1196- else if (!stricmp(actionCstr, "Account.ListAutoAcceptRules.1"))
1197- {
1198- gVoiceClient->accountListAutoAcceptRulesResponse(statusCode, statusString);
1199- }
1200- else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
1201+ else if (actionString == "Account.ChannelGetList.1")
1202 {
1203- // We don't need to process these, but they're so spammy we don't want to log them.
1204- squelchDebugOutput = true;
1205+ gVoiceClient->channelGetListResponse(statusCode, statusString);
1206 }
1207 /*
1208- else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
1209+ else if (actionString == "Connector.AccountCreate.1")
1210 {
1211- gVoiceClient->channelGetListResponse(statusCode, statusString);
1212+
1213 }
1214- else if (!stricmp(actionCstr, "Connector.AccountCreate.1"))
1215+ else if (actionString == "Connector.MuteLocalMic.1")
1216 {
1217
1218 }
1219- else if (!stricmp(actionCstr, "Connector.MuteLocalMic.1"))
1220+ else if (actionString == "Connector.MuteLocalSpeaker.1")
1221 {
1222
1223 }
1224- else if (!stricmp(actionCstr, "Connector.MuteLocalSpeaker.1"))
1225+ else if (actionString == "Connector.SetLocalMicVolume.1")
1226 {
1227
1228 }
1229- else if (!stricmp(actionCstr, "Connector.SetLocalMicVolume.1"))
1230+ else if (actionString == "Connector.SetLocalSpeakerVolume.1")
1231 {
1232
1233 }
1234- else if (!stricmp(actionCstr, "Connector.SetLocalSpeakerVolume.1"))
1235+ else if (actionString == "Session.ListenerSetPosition.1")
1236 {
1237
1238 }
1239- else if (!stricmp(actionCstr, "Session.ListenerSetPosition.1"))
1240+ else if (actionString == "Session.SpeakerSetPosition.1")
1241 {
1242
1243 }
1244- else if (!stricmp(actionCstr, "Session.SpeakerSetPosition.1"))
1245+ else if (actionString == "Session.Set3DPosition.1")
1246 {
1247
1248 }
1249- else if (!stricmp(actionCstr, "Session.AudioSourceSetPosition.1"))
1250+ else if (actionString == "Session.AudioSourceSetPosition.1")
1251 {
1252
1253 }
1254- else if (!stricmp(actionCstr, "Session.GetChannelParticipants.1"))
1255+ else if (actionString == "Session.GetChannelParticipants.1")
1256 {
1257
1258 }
1259- else if (!stricmp(actionCstr, "Account.ChannelCreate.1"))
1260+ else if (actionString == "Account.ChannelCreate.1")
1261 {
1262
1263 }
1264- else if (!stricmp(actionCstr, "Account.ChannelUpdate.1"))
1265+ else if (actionString == "Account.ChannelUpdate.1")
1266 {
1267
1268 }
1269- else if (!stricmp(actionCstr, "Account.ChannelDelete.1"))
1270+ else if (actionString == "Account.ChannelDelete.1")
1271 {
1272
1273 }
1274- else if (!stricmp(actionCstr, "Account.ChannelCreateAndInvite.1"))
1275+ else if (actionString == "Account.ChannelCreateAndInvite.1")
1276 {
1277
1278 }
1279- else if (!stricmp(actionCstr, "Account.ChannelFolderCreate.1"))
1280+ else if (actionString == "Account.ChannelFolderCreate.1")
1281 {
1282
1283 }
1284- else if (!stricmp(actionCstr, "Account.ChannelFolderUpdate.1"))
1285+ else if (actionString == "Account.ChannelFolderUpdate.1")
1286 {
1287
1288 }
1289- else if (!stricmp(actionCstr, "Account.ChannelFolderDelete.1"))
1290+ else if (actionString == "Account.ChannelFolderDelete.1")
1291 {
1292
1293 }
1294- else if (!stricmp(actionCstr, "Account.ChannelAddModerator.1"))
1295+ else if (actionString == "Account.ChannelAddModerator.1")
1296 {
1297
1298 }
1299- else if (!stricmp(actionCstr, "Account.ChannelDeleteModerator.1"))
1300+ else if (actionString == "Account.ChannelDeleteModerator.1")
1301 {
1302
1303 }
1304@@ -979,18 +704,9 @@ class LLVoiceClientMuteListObserver : public LLMuteListObserver
1305 {
1306 /* virtual */ void onChange() { gVoiceClient->muteListChanged();}
1307 };
1308-
1309-class LLVoiceClientFriendsObserver : public LLFriendObserver
1310-{
1311-public:
1312- /* virtual */ void changed(U32 mask) { gVoiceClient->updateFriends(mask);}
1313-};
1314-
1315 static LLVoiceClientMuteListObserver mutelist_listener;
1316 static bool sMuteListListener_listening = false;
1317
1318-static LLVoiceClientFriendsObserver *friendslist_listener = NULL;
1319-
1320 ///////////////////////////////////////////////////////////////////////////////////////////////
1321
1322 class LLVoiceClientCapResponder : public LLHTTPClient::Responder
1323@@ -1014,8 +730,11 @@ void LLVoiceClientCapResponder::error(U32 status, const std::string& reason)
1324 void LLVoiceClientCapResponder::result(const LLSD& content)
1325 {
1326 LLSD::map_const_iterator iter;
1327-
1328- LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
1329+ for(iter = content.beginMap(); iter != content.endMap(); ++iter)
1330+ {
1331+ LL_DEBUGS("Voice") << "LLVoiceClientCapResponder::result got "
1332+ << iter->first << LL_ENDL;
1333+ }
1334
1335 if ( content.has("voice_credentials") )
1336 {
1337@@ -1101,26 +820,26 @@ LLVoiceClient::LLVoiceClient()
1338 mUserPTTState = false;
1339 mMuteMic = false;
1340 mSessionTerminateRequested = false;
1341- mRelogRequested = false;
1342 mCommandCookie = 0;
1343+ mNonSpatialChannel = false;
1344+ mNextSessionSpatial = true;
1345+ mNextSessionNoReconnect = false;
1346+ mSessionP2P = false;
1347 mCurrentParcelLocalID = 0;
1348 mLoginRetryCount = 0;
1349+ mVivoxErrorStatusCode = 0;
1350
1351+ mNextSessionResetOnClose = false;
1352+ mSessionResetOnClose = false;
1353 mSpeakerVolume = 0;
1354 mMicVolume = 0;
1355
1356- mAudioSession = NULL;
1357- mAudioSessionChanged = false;
1358-
1359 // Initial dirty state
1360 mSpatialCoordsDirty = false;
1361 mPTTDirty = true;
1362- mFriendsListDirty = true;
1363+ mVolumeDirty = true;
1364 mSpeakerVolumeDirty = true;
1365 mMicVolumeDirty = true;
1366- mBuddyListMapPopulated = false;
1367- mBlockRulesListReceived = false;
1368- mAutoAcceptRulesListReceived = false;
1369 mCaptureDeviceDirty = false;
1370 mRenderDeviceDirty = false;
1371
1372@@ -1141,12 +860,14 @@ LLVoiceClient::LLVoiceClient()
1373 // gMuteListp isn't set up at this point, so we defer this until later.
1374 // gMuteListp->addObserver(&mutelist_listener);
1375
1376+ mParticipantMapChanged = false;
1377+
1378 // stash the pump for later use
1379 // This now happens when init() is called instead.
1380 mPump = NULL;
1381
1382 #if LL_DARWIN || LL_LINUX
1383- // HACK: THIS DOES NOT BELONG HERE
1384+ // MBW -- XXX -- THIS DOES NOT BELONG HERE
1385 // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
1386 // This should cause us to ignore SIGPIPE and handle the error through proper channels.
1387 // This should really be set up elsewhere. Where should it go?
1388@@ -1182,10 +903,8 @@ void LLVoiceClient::terminate()
1389 {
1390 if(gVoiceClient)
1391 {
1392-// gVoiceClient->leaveAudioSession();
1393+ gVoiceClient->sessionTerminateSendMessage();
1394 gVoiceClient->logout();
1395- // As of SDK version 4885, this should no longer be necessary. It will linger after the socket close if it needs to.
1396- // ms_sleep(2000);
1397 gVoiceClient->connectorShutdown();
1398 gVoiceClient->closeSocket(); // Need to do this now -- bad things happen if the destructor does it later.
1399
1400@@ -1210,13 +929,13 @@ void LLVoiceClient::updateSettings()
1401 setPTTKey(keyString);
1402 setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
1403 setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
1404+ std::string serverName = gSavedSettings.getString("VivoxDebugServerName");
1405+ setVivoxDebugServerName(serverName);
1406
1407 std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
1408 setCaptureDevice(inputDevice);
1409 std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
1410 setRenderDevice(outputDevice);
1411- F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
1412- setMicGain(mic_level);
1413 setLipSyncEnabled(gSavedSettings.getBOOL("LipSyncEnabled"));
1414 }
1415
1416@@ -1232,10 +951,9 @@ bool LLVoiceClient::writeString(const std::string &str)
1417 apr_size_t size = (apr_size_t)str.size();
1418 apr_size_t written = size;
1419
1420- //MARK: Turn this on to log outgoing XML
1421-// LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
1422+ LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
1423
1424- // check return code - sockets will fail (broken, etc.)
1425+ // MBW -- XXX -- check return code - sockets will fail (broken, etc.)
1426 err = apr_socket_send(
1427 mSocket->getSocket(),
1428 (const char*)str.data(),
1429@@ -1246,7 +964,7 @@ bool LLVoiceClient::writeString(const std::string &str)
1430 // Success.
1431 result = true;
1432 }
1433- // TODO: handle partial writes (written is number of bytes written)
1434+ // MBW -- XXX -- handle partial writes (written is number of bytes written)
1435 // Need to set socket to non-blocking before this will work.
1436 // else if(APR_STATUS_IS_EAGAIN(err))
1437 // {
1438@@ -1270,7 +988,7 @@ bool LLVoiceClient::writeString(const std::string &str)
1439 void LLVoiceClient::connectorCreate()
1440 {
1441 std::ostringstream stream;
1442- std::string logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
1443+ std::string logpath;
1444 std::string loglevel = "0";
1445
1446 // Transition to stateConnectorStarted when the connector handle comes back.
1447@@ -1282,20 +1000,20 @@ void LLVoiceClient::connectorCreate()
1448 {
1449 LL_DEBUGS("Voice") << "creating connector with logging enabled" << LL_ENDL;
1450 loglevel = "10";
1451+ logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
1452 }
1453
1454 stream
1455 << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.Create.1\">"
1456 << "<ClientName>V2 SDK</ClientName>"
1457- << "<AccountManagementServer>" << mVoiceAccountServerURI << "</AccountManagementServer>"
1458- << "<Mode>Normal</Mode>"
1459+ << "<AccountManagementServer>" << mAccountServerURI << "</AccountManagementServer>"
1460 << "<Logging>"
1461+ << "<Enabled>false</Enabled>"
1462 << "<Folder>" << logpath << "</Folder>"
1463 << "<FileNamePrefix>Connector</FileNamePrefix>"
1464 << "<FileNameSuffix>.log</FileNameSuffix>"
1465 << "<LogLevel>" << loglevel << "</LogLevel>"
1466 << "</Logging>"
1467- << "<Application>SecondLifeViewer.1</Application>"
1468 << "</Request>\n\n\n";
1469
1470 writeString(stream.str());
1471@@ -1333,6 +1051,20 @@ void LLVoiceClient::userAuthorized(const std::string& firstName, const std::stri
1472
1473 sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid();
1474
1475+ // MBW -- XXX -- Enable this when the bhd.vivox.com server gets a real ssl cert.
1476+ if(sConnectingToAgni)
1477+ {
1478+ // Use the release account server
1479+ mAccountServerName = "bhr.vivox.com";
1480+ mAccountServerURI = "https://www." + mAccountServerName + "/api2/";
1481+ }
1482+ else
1483+ {
1484+ // Use the development account server
1485+ mAccountServerName = gSavedSettings.getString("VivoxDebugServerName");
1486+ mAccountServerURI = "https://www." + mAccountServerName + "/api2/";
1487+ }
1488+
1489 mAccountName = nameFromID(agentID);
1490 }
1491
1492@@ -1354,69 +1086,24 @@ void LLVoiceClient::requestVoiceAccountProvision(S32 retries)
1493 }
1494
1495 void LLVoiceClient::login(
1496- const std::string& account_name,
1497- const std::string& password,
1498- const std::string& voice_sip_uri_hostname,
1499- const std::string& voice_account_server_uri)
1500+ const std::string& accountName,
1501+ const std::string &password)
1502 {
1503- mVoiceSIPURIHostName = voice_sip_uri_hostname;
1504- mVoiceAccountServerURI = voice_account_server_uri;
1505-
1506- if(!mAccountHandle.empty())
1507+ if((getState() >= stateLoggingIn) && (getState() < stateLoggedOut))
1508 {
1509- // Already logged in.
1510- LL_WARNS("Voice") << "Called while already logged in." << LL_ENDL;
1511-
1512- // Don't process another login.
1513- return;
1514+ // Already logged in. This is an internal error.
1515+ LL_ERRS("Voice") << "Can't login again. Called from wrong state." << LL_ENDL;
1516 }
1517- else if ( account_name != mAccountName )
1518+ else if ( accountName != mAccountName )
1519 {
1520 //TODO: error?
1521- LL_WARNS("Voice") << "Wrong account name! " << account_name
1522+ LL_WARNS("Voice") << "Wrong account name! " << accountName
1523 << " instead of " << mAccountName << LL_ENDL;
1524 }
1525 else
1526 {
1527 mAccountPassword = password;
1528 }
1529-
1530- std::string debugSIPURIHostName = gSavedSettings.getString("VivoxDebugSIPURIHostName");
1531-
1532- if( !debugSIPURIHostName.empty() )
1533- {
1534- mVoiceSIPURIHostName = debugSIPURIHostName;
1535- }
1536-
1537- if( mVoiceSIPURIHostName.empty() )
1538- {
1539- // we have an empty account server name
1540- // so we fall back to hardcoded defaults
1541-
1542- if(sConnectingToAgni)
1543- {
1544- // Use the release account server
1545- mVoiceSIPURIHostName = "bhr.vivox.com";
1546- }
1547- else
1548- {
1549- // Use the development account server
1550- mVoiceSIPURIHostName = "bhd.vivox.com";
1551- }
1552- }
1553-
1554- std::string debugAccountServerURI = gSavedSettings.getString("VivoxDebugVoiceAccountServerURI");
1555-
1556- if( !debugAccountServerURI.empty() )
1557- {
1558- mVoiceAccountServerURI = debugAccountServerURI;
1559- }
1560-
1561- if( mVoiceAccountServerURI.empty() )
1562- {
1563- // If the account server URI isn't specified, construct it from the SIP URI hostname
1564- mVoiceAccountServerURI = "https://www." + mVoiceSIPURIHostName + "/api2/";
1565- }
1566 }
1567
1568 void LLVoiceClient::idle(void* user_data)
1569@@ -1434,16 +1121,11 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
1570
1571 switch(inState)
1572 {
1573- CASE(stateDisableCleanup);
1574 CASE(stateDisabled);
1575 CASE(stateStart);
1576 CASE(stateDaemonLaunched);
1577 CASE(stateConnecting);
1578- CASE(stateConnected);
1579 CASE(stateIdle);
1580- CASE(stateMicTuningStart);
1581- CASE(stateMicTuningRunning);
1582- CASE(stateMicTuningStop);
1583 CASE(stateConnectorStart);
1584 CASE(stateConnectorStarting);
1585 CASE(stateConnectorStarted);
1586@@ -1452,8 +1134,12 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
1587 CASE(stateNeedsLogin);
1588 CASE(stateLoggingIn);
1589 CASE(stateLoggedIn);
1590- CASE(stateCreatingSessionGroup);
1591 CASE(stateNoChannel);
1592+ CASE(stateMicTuningStart);
1593+ CASE(stateMicTuningRunning);
1594+ CASE(stateMicTuningStop);
1595+ CASE(stateSessionCreate);
1596+ CASE(stateSessionConnect);
1597 CASE(stateJoiningSession);
1598 CASE(stateSessionJoined);
1599 CASE(stateRunning);
1600@@ -1470,6 +1156,7 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
1601 CASE(stateJoinSessionFailed);
1602 CASE(stateJoinSessionFailedWaiting);
1603 CASE(stateJail);
1604+ CASE(stateMicTuningNoLogin);
1605 }
1606
1607 #undef CASE
1608@@ -1491,7 +1178,6 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv
1609 CASE(STATUS_JOINING);
1610 CASE(STATUS_JOINED);
1611 CASE(STATUS_LEFT_CHANNEL);
1612- CASE(STATUS_VOICE_DISABLED);
1613 CASE(BEGIN_ERROR_STATUS);
1614 CASE(ERROR_CHANNEL_FULL);
1615 CASE(ERROR_CHANNEL_LOCKED);
1616@@ -1525,13 +1211,9 @@ void LLVoiceClient::stateMachine()
1617 {
1618 updatePosition();
1619 }
1620- else if(mTuningMode)
1621- {
1622- // Tuning mode is special -- it needs to launch SLVoice even if voice is disabled.
1623- }
1624 else
1625 {
1626- if((getState() != stateDisabled) && (getState() != stateDisableCleanup))
1627+ if(getState() != stateDisabled)
1628 {
1629 // User turned off voice support. Send the cleanup messages, close the socket, and reset.
1630 if(!mConnected)
1631@@ -1541,10 +1223,13 @@ void LLVoiceClient::stateMachine()
1632 killGateway();
1633 }
1634
1635+ sessionTerminateSendMessage();
1636 logout();
1637 connectorShutdown();
1638-
1639- setState(stateDisableCleanup);
1640+ closeSocket();
1641+ removeAllParticipants();
1642+
1643+ setState(stateDisabled);
1644 }
1645 }
1646
1647@@ -1559,7 +1244,7 @@ void LLVoiceClient::stateMachine()
1648 std::string regionName = region->getName();
1649 std::string capURI = region->getCapability("ParcelVoiceInfoRequest");
1650
1651-// LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL;
1652+ LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL;
1653
1654 // The region name starts out empty and gets filled in later.
1655 // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
1656@@ -1580,30 +1265,13 @@ void LLVoiceClient::stateMachine()
1657
1658 switch(getState())
1659 {
1660- //MARK: stateDisableCleanup
1661- case stateDisableCleanup:
1662- // Clean up and reset everything.
1663- closeSocket();
1664- deleteAllSessions();
1665- deleteAllBuddies();
1666-
1667- mConnectorHandle.clear();
1668- mAccountHandle.clear();
1669- mAccountPassword.clear();
1670- mVoiceAccountServerURI.clear();
1671-
1672- setState(stateDisabled);
1673- break;
1674-
1675- //MARK: stateDisabled
1676 case stateDisabled:
1677- if(mTuningMode || (mVoiceEnabled && !mAccountName.empty()))
1678+ if(mVoiceEnabled && (!mAccountName.empty() || mTuningMode))
1679 {
1680 setState(stateStart);
1681 }
1682 break;
1683
1684- //MARK: stateStart
1685 case stateStart:
1686 if(gSavedSettings.getBOOL("CmdLineDisableVoice"))
1687 {
1688@@ -1634,9 +1302,7 @@ void LLVoiceClient::stateMachine()
1689 if(!LLFile::stat(exe_path, &s))
1690 {
1691 // vivox executable exists. Build the command line and launch the daemon.
1692- // SLIM SDK: these arguments are no longer necessary.
1693-// std::string args = " -p tcp -h -c";
1694- std::string args;
1695+ std::string args = " -p tcp -h -c";
1696 std::string cmd;
1697 std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
1698
1699@@ -1721,15 +1387,14 @@ void LLVoiceClient::stateMachine()
1700 }
1701 else
1702 {
1703- LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL;
1704+ LL_INFOS("Voice") << exe_path << "not found." << LL_ENDL;
1705 }
1706 }
1707 else
1708 {
1709- // SLIM SDK: port changed from 44124 to 44125.
1710 // We can connect to a client gateway running on another host. This is useful for testing.
1711 // To do this, launch the gateway on a nearby host like this:
1712- // vivox-gw.exe -p tcp -i 0.0.0.0:44125
1713+ // vivox-gw.exe -p tcp -i 0.0.0.0:44124
1714 // and put that host's IP address here.
1715 mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost"), gSavedSettings.getU32("VoicePort"));
1716 }
1717@@ -1741,23 +1406,17 @@ void LLVoiceClient::stateMachine()
1718
1719 // Dirty the states we'll need to sync with the daemon when it comes up.
1720 mPTTDirty = true;
1721- mMicVolumeDirty = true;
1722 mSpeakerVolumeDirty = true;
1723- mSpeakerMuteDirty = true;
1724 // These only need to be set if they're not default (i.e. empty string).
1725 mCaptureDeviceDirty = !mCaptureDevice.empty();
1726 mRenderDeviceDirty = !mRenderDevice.empty();
1727-
1728- mMainSessionGroupHandle.clear();
1729 }
1730 break;
1731-
1732- //MARK: stateDaemonLaunched
1733+
1734 case stateDaemonLaunched:
1735+ LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
1736 if(mUpdateTimer.hasExpired())
1737 {
1738- LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
1739-
1740 mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
1741
1742 if(!mSocket)
1743@@ -1778,7 +1437,6 @@ void LLVoiceClient::stateMachine()
1744 }
1745 break;
1746
1747- //MARK: stateConnecting
1748 case stateConnecting:
1749 // Can't do this until we have the pump available.
1750 if(mPump)
1751@@ -1796,34 +1454,48 @@ void LLVoiceClient::stateMachine()
1752
1753 mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
1754
1755- setState(stateConnected);
1756+ setState(stateIdle);
1757 }
1758
1759 break;
1760
1761- //MARK: stateConnected
1762- case stateConnected:
1763+ case stateIdle:
1764 // Initial devices query
1765 getCaptureDevicesSendMessage();
1766 getRenderDevicesSendMessage();
1767
1768 mLoginRetryCount = 0;
1769-
1770- setState(stateIdle);
1771+
1772+ setState(stateConnectorStart);
1773+
1774 break;
1775-
1776- //MARK: stateIdle
1777- case stateIdle:
1778- // This is the idle state where we're connected to the daemon but haven't set up a connector yet.
1779- if(mTuningMode)
1780+
1781+ case stateConnectorStart:
1782+ if(!mVoiceEnabled)
1783 {
1784- mTuningExitState = stateIdle;
1785+ // We were never logged in. This will shut down the connector.
1786+ setState(stateLoggedOut);
1787+ }
1788+ else if(!mAccountServerURI.empty())
1789+ {
1790+ connectorCreate();
1791+ }
1792+ else if(mTuningMode)
1793+ {
1794+ mTuningExitState = stateConnectorStart;
1795 setState(stateMicTuningStart);
1796 }
1797- else if(!mVoiceEnabled)
1798+ break;
1799+
1800+ case stateConnectorStarting: // waiting for connector handle
1801+ // connectorCreateResponse() will transition from here to stateConnectorStarted.
1802+ break;
1803+
1804+ case stateConnectorStarted: // connector handle received
1805+ if(!mVoiceEnabled)
1806 {
1807- // We never started up the connector. This will shut down the daemon.
1808- setState(stateConnectorStopped);
1809+ // We were never logged in. This will shut down the connector.
1810+ setState(stateLoggedOut);
1811 }
1812 else if(!mAccountName.empty())
1813 {
1814@@ -1837,13 +1509,12 @@ void LLVoiceClient::stateMachine()
1815 {
1816 requestVoiceAccountProvision();
1817 }
1818- setState(stateConnectorStart);
1819+ setState(stateNeedsLogin);
1820 }
1821 }
1822 }
1823 break;
1824-
1825- //MARK: stateMicTuningStart
1826+
1827 case stateMicTuningStart:
1828 if(mUpdateTimer.hasExpired())
1829 {
1830@@ -1851,9 +1522,19 @@ void LLVoiceClient::stateMachine()
1831 {
1832 // These can't be changed while in tuning mode. Set them before starting.
1833 std::ostringstream stream;
1834-
1835- buildSetCaptureDevice(stream);
1836- buildSetRenderDevice(stream);
1837+
1838+ if(mCaptureDeviceDirty)
1839+ {
1840+ buildSetCaptureDevice(stream);
1841+ }
1842+
1843+ if(mRenderDeviceDirty)
1844+ {
1845+ buildSetRenderDevice(stream);
1846+ }
1847+
1848+ mCaptureDeviceDirty = false;
1849+ mRenderDeviceDirty = false;
1850
1851 if(!stream.str().empty())
1852 {
1853@@ -1875,9 +1556,8 @@ void LLVoiceClient::stateMachine()
1854
1855 break;
1856
1857- //MARK: stateMicTuningRunning
1858 case stateMicTuningRunning:
1859- if(!mTuningMode || mCaptureDeviceDirty || mRenderDeviceDirty)
1860+ if(!mTuningMode || !mVoiceEnabled || mSessionTerminateRequested || mCaptureDeviceDirty || mRenderDeviceDirty)
1861 {
1862 // All of these conditions make us leave tuning mode.
1863 setState(stateMicTuningStop);
1864@@ -1917,7 +1597,6 @@ void LLVoiceClient::stateMachine()
1865 }
1866 break;
1867
1868- //MARK: stateMicTuningStop
1869 case stateMicTuningStop:
1870 {
1871 // transition out of mic tuning
1872@@ -1931,40 +1610,7 @@ void LLVoiceClient::stateMachine()
1873
1874 }
1875 break;
1876-
1877- //MARK: stateConnectorStart
1878- case stateConnectorStart:
1879- if(!mVoiceEnabled)
1880- {
1881- // We were never logged in. This will shut down the connector.
1882- setState(stateLoggedOut);
1883- }
1884- else if(!mVoiceAccountServerURI.empty())
1885- {
1886- connectorCreate();
1887- }
1888- break;
1889-
1890- //MARK: stateConnectorStarting
1891- case stateConnectorStarting: // waiting for connector handle
1892- // connectorCreateResponse() will transition from here to stateConnectorStarted.
1893- break;
1894-
1895- //MARK: stateConnectorStarted
1896- case stateConnectorStarted: // connector handle received
1897- if(!mVoiceEnabled)
1898- {
1899- // We were never logged in. This will shut down the connector.
1900- setState(stateLoggedOut);
1901- }
1902- else
1903- {
1904- // The connector is started. Send a login message.
1905- setState(stateNeedsLogin);
1906- }
1907- break;
1908-
1909- //MARK: stateLoginRetry
1910+
1911 case stateLoginRetry:
1912 if(mLoginRetryCount == 0)
1913 {
1914@@ -1988,7 +1634,6 @@ void LLVoiceClient::stateMachine()
1915 }
1916 break;
1917
1918- //MARK: stateLoginRetryWait
1919 case stateLoginRetryWait:
1920 if(mUpdateTimer.hasExpired())
1921 {
1922@@ -1996,7 +1641,6 @@ void LLVoiceClient::stateMachine()
1923 }
1924 break;
1925
1926- //MARK: stateNeedsLogin
1927 case stateNeedsLogin:
1928 if(!mAccountPassword.empty())
1929 {
1930@@ -2005,22 +1649,16 @@ void LLVoiceClient::stateMachine()
1931 }
1932 break;
1933
1934- //MARK: stateLoggingIn
1935 case stateLoggingIn: // waiting for account handle
1936 // loginResponse() will transition from here to stateLoggedIn.
1937 break;
1938
1939- //MARK: stateLoggedIn
1940 case stateLoggedIn: // account handle received
1941+ // Initial kick-off of channel lookup logic
1942+ parcelChanged();
1943
1944 notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
1945
1946- // request the current set of block rules (we'll need them when updating the friends list)
1947- accountListBlockRulesSendMessage();
1948-
1949- // request the current set of auto-accept rules
1950- accountListAutoAcceptRulesSendMessage();
1951-
1952 // Set up the mute list observer if it hasn't been set up already.
1953 if((!sMuteListListener_listening))
1954 {
1955@@ -2028,67 +1666,13 @@ void LLVoiceClient::stateMachine()
1956 sMuteListListener_listening = true;
1957 }
1958
1959- // Set up the friends list observer if it hasn't been set up already.
1960- if(friendslist_listener == NULL)
1961- {
1962- friendslist_listener = new LLVoiceClientFriendsObserver;
1963- LLAvatarTracker::instance().addObserver(friendslist_listener);
1964- }
1965-
1966- // Set the initial state of mic mute, local speaker volume, etc.
1967- {
1968- std::ostringstream stream;
1969-
1970- buildLocalAudioUpdates(stream);
1971-
1972- if(!stream.str().empty())
1973- {
1974- writeString(stream.str());
1975- }
1976- }
1977-
1978-#if USE_SESSION_GROUPS
1979- // create the main session group
1980- sessionGroupCreateSendMessage();
1981-
1982- setState(stateCreatingSessionGroup);
1983-#else
1984- // Not using session groups -- skip the stateCreatingSessionGroup state.
1985 setState(stateNoChannel);
1986-
1987- // Initial kick-off of channel lookup logic
1988- parcelChanged();
1989-#endif
1990- break;
1991-
1992- //MARK: stateCreatingSessionGroup
1993- case stateCreatingSessionGroup:
1994- if(mSessionTerminateRequested || !mVoiceEnabled)
1995- {
1996- // TODO: Question: is this the right way out of this state
1997- setState(stateSessionTerminated);
1998- }
1999- else if(!mMainSessionGroupHandle.empty())
2000- {
2001- setState(stateNoChannel);
2002-
2003- // Start looped recording (needed for "panic button" anti-griefing tool)
2004- recordingLoopStart();
2005-
2006- // Initial kick-off of channel lookup logic
2007- parcelChanged();
2008- }
2009 break;
2010
2011- //MARK: stateNoChannel
2012 case stateNoChannel:
2013- // Do this here as well as inside sendPositionalUpdate().
2014- // Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
2015- sendFriendsListUpdates();
2016-
2017 if(mSessionTerminateRequested || !mVoiceEnabled)
2018 {
2019- // TODO: Question: Is this the right way out of this state?
2020+ // MBW -- XXX -- Is this the right way out of this state?
2021 setState(stateSessionTerminated);
2022 }
2023 else if(mTuningMode)
2024@@ -2096,49 +1680,30 @@ void LLVoiceClient::stateMachine()
2025 mTuningExitState = stateNoChannel;
2026 setState(stateMicTuningStart);
2027 }
2028- else if(sessionNeedsRelog(mNextAudioSession))
2029+ else if(!mNextSessionHandle.empty())
2030 {
2031- requestRelog();
2032- setState(stateSessionTerminated);
2033+ setState(stateSessionConnect);
2034 }
2035- else if(mNextAudioSession)
2036- {
2037- sessionState *oldSession = mAudioSession;
2038-
2039- mAudioSession = mNextAudioSession;
2040- if(!mAudioSession->mReconnect)
2041- {
2042- mNextAudioSession = NULL;
2043- }
2044-
2045- // The old session may now need to be deleted.
2046- reapSession(oldSession);
2047-
2048- if(!mAudioSession->mHandle.empty())
2049- {
2050- // Connect to a session by session handle
2051-
2052- sessionMediaConnectSendMessage(mAudioSession);
2053- }
2054- else
2055- {
2056- // Connect to a session by URI
2057- sessionCreateSendMessage(mAudioSession, true, false);
2058- }
2059-
2060- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
2061- setState(stateJoiningSession);
2062- }
2063- else if(!mSpatialSessionURI.empty())
2064+ else if(!mNextSessionURI.empty())
2065 {
2066- // If we're not headed elsewhere and have a spatial URI, return to spatial.
2067- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
2068+ setState(stateSessionCreate);
2069 }
2070 break;
2071
2072- //MARK: stateJoiningSession
2073+ case stateSessionCreate:
2074+ sessionCreateSendMessage();
2075+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
2076+ setState(stateJoiningSession);
2077+ break;
2078+
2079+ case stateSessionConnect:
2080+ sessionConnectSendMessage();
2081+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
2082+ setState(stateJoiningSession);
2083+ break;
2084+
2085 case stateJoiningSession: // waiting for session handle
2086- // joinedAudioSession() will transition from here to stateSessionJoined.
2087+ // sessionCreateResponse() will transition from here to stateSessionJoined.
2088 if(!mVoiceEnabled)
2089 {
2090 // User bailed out during connect -- jump straight to teardown.
2091@@ -2146,27 +1711,30 @@ void LLVoiceClient::stateMachine()
2092 }
2093 else if(mSessionTerminateRequested)
2094 {
2095- if(mAudioSession && !mAudioSession->mHandle.empty())
2096+ if(!mSessionHandle.empty())
2097 {
2098 // Only allow direct exits from this state in p2p calls (for cancelling an invite).
2099 // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
2100- if(mAudioSession->mIsP2P)
2101+ if(mSessionP2P)
2102 {
2103- sessionMediaDisconnectSendMessage(mAudioSession);
2104+ sessionTerminateSendMessage();
2105 setState(stateSessionTerminated);
2106 }
2107 }
2108 }
2109 break;
2110
2111- //MARK: stateSessionJoined
2112 case stateSessionJoined: // session handle received
2113- // It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
2114- // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
2115- // For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
2116+ // MBW -- XXX -- It appears that I need to wait for BOTH the Session.Create response and the SessionStateChangeEvent with state 4
2117+ // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
2118+ // For now, the Session.Create response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
2119 // This is a cheap way to make sure both have happened before proceeding.
2120- if(mAudioSession && mAudioSession->mVoiceEnabled)
2121+ if(!mSessionHandle.empty())
2122 {
2123+ // Events that need to happen when a session is joined could go here.
2124+ // Maybe send initial spatial data?
2125+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
2126+
2127 // Dirty state that may need to be sync'ed with the daemon.
2128 mPTTDirty = true;
2129 mSpeakerVolumeDirty = true;
2130@@ -2177,11 +1745,6 @@ void LLVoiceClient::stateMachine()
2131 // Start the throttle timer
2132 mUpdateTimer.start();
2133 mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
2134-
2135- // Events that need to happen when a session is joined could go here.
2136- // Maybe send initial spatial data?
2137- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
2138-
2139 }
2140 else if(!mVoiceEnabled)
2141 {
2142@@ -2192,20 +1755,21 @@ void LLVoiceClient::stateMachine()
2143 {
2144 // Only allow direct exits from this state in p2p calls (for cancelling an invite).
2145 // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
2146- if(mAudioSession && mAudioSession->mIsP2P)
2147+ if(mSessionP2P)
2148 {
2149- sessionMediaDisconnectSendMessage(mAudioSession);
2150+ sessionTerminateSendMessage();
2151 setState(stateSessionTerminated);
2152 }
2153 }
2154 break;
2155
2156- //MARK: stateRunning
2157 case stateRunning: // steady state
2158+ // sessionTerminateSendMessage() will transition from here to stateLeavingSession
2159+
2160 // Disabling voice or disconnect requested.
2161 if(!mVoiceEnabled || mSessionTerminateRequested)
2162 {
2163- leaveAudioSession();
2164+ sessionTerminateSendMessage();
2165 }
2166 else
2167 {
2168@@ -2238,7 +1802,7 @@ void LLVoiceClient::stateMachine()
2169 }
2170 }
2171
2172- if(!inSpatialChannel())
2173+ if(mNonSpatialChannel)
2174 {
2175 // When in a non-spatial channel, never send positional updates.
2176 mSpatialCoordsDirty = false;
2177@@ -2251,7 +1815,7 @@ void LLVoiceClient::stateMachine()
2178
2179 // 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)
2180 // or every 10hz, whichever is sooner.
2181- if((mAudioSession && mAudioSession->mVolumeDirty) || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
2182+ if(mVolumeDirty || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
2183 {
2184 mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
2185 sendPositionalUpdate();
2186@@ -2259,38 +1823,25 @@ void LLVoiceClient::stateMachine()
2187 }
2188 break;
2189
2190- //MARK: stateLeavingSession
2191 case stateLeavingSession: // waiting for terminate session response
2192 // The handler for the Session.Terminate response will transition from here to stateSessionTerminated.
2193 break;
2194
2195- //MARK: stateSessionTerminated
2196 case stateSessionTerminated:
2197+ // Always reset the terminate request flag when we get here.
2198+ mSessionTerminateRequested = false;
2199
2200- // Must do this first, since it uses mAudioSession.
2201 notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
2202-
2203- if(mAudioSession)
2204- {
2205- sessionState *oldSession = mAudioSession;
2206
2207- mAudioSession = NULL;
2208- // We just notified status observers about this change. Don't do it again.
2209- mAudioSessionChanged = false;
2210-
2211- // The old session may now need to be deleted.
2212- reapSession(oldSession);
2213- }
2214- else
2215+ if(mVoiceEnabled)
2216 {
2217- LL_WARNS("Voice") << "stateSessionTerminated with NULL mAudioSession" << LL_ENDL;
2218- }
2219-
2220- // Always reset the terminate request flag when we get here.
2221- mSessionTerminateRequested = false;
2222-
2223- if(mVoiceEnabled && !mRelogRequested)
2224- {
2225+ // SPECIAL CASE: if going back to spatial but in a parcel with an empty URI, transfer the non-spatial flag now.
2226+ // 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.
2227+ if(mNextSessionSpatial && mNextSessionURI.empty())
2228+ {
2229+ mNonSpatialChannel = !mNextSessionSpatial;
2230+ }
2231+
2232 // Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state).
2233 setState(stateNoChannel);
2234 }
2235@@ -2298,67 +1849,49 @@ void LLVoiceClient::stateMachine()
2236 {
2237 // Shutting down voice, continue with disconnecting.
2238 logout();
2239-
2240- // The state machine will take it from here
2241- mRelogRequested = false;
2242 }
2243
2244 break;
2245
2246- //MARK: stateLoggingOut
2247 case stateLoggingOut: // waiting for logout response
2248 // The handler for the Account.Logout response will transition from here to stateLoggedOut.
2249 break;
2250- //MARK: stateLoggedOut
2251 case stateLoggedOut: // logout response received
2252 // shut down the connector
2253 connectorShutdown();
2254 break;
2255
2256- //MARK: stateConnectorStopping
2257 case stateConnectorStopping: // waiting for connector stop
2258 // The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped.
2259 break;
2260
2261- //MARK: stateConnectorStopped
2262 case stateConnectorStopped: // connector stop received
2263- setState(stateDisableCleanup);
2264+ // Clean up and reset everything.
2265+ closeSocket();
2266+ removeAllParticipants();
2267+ setState(stateDisabled);
2268 break;
2269
2270- //MARK: stateConnectorFailed
2271 case stateConnectorFailed:
2272 setState(stateConnectorFailedWaiting);
2273 break;
2274- //MARK: stateConnectorFailedWaiting
2275 case stateConnectorFailedWaiting:
2276 break;
2277
2278- //MARK: stateLoginFailed
2279 case stateLoginFailed:
2280 setState(stateLoginFailedWaiting);
2281 break;
2282- //MARK: stateLoginFailedWaiting
2283 case stateLoginFailedWaiting:
2284 // No way to recover from these. Yet.
2285 break;
2286
2287- //MARK: stateJoinSessionFailed
2288 case stateJoinSessionFailed:
2289 // Transition to error state. Send out any notifications here.
2290- if(mAudioSession)
2291- {
2292- LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mAudioSession->mErrorStatusCode << "): " << mAudioSession->mErrorStatusString << LL_ENDL;
2293- }
2294- else
2295- {
2296- LL_WARNS("Voice") << "stateJoinSessionFailed with no current session" << LL_ENDL;
2297- }
2298-
2299+ LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mVivoxErrorStatusCode << "): " << mVivoxErrorStatusString << LL_ENDL;
2300 notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
2301 setState(stateJoinSessionFailedWaiting);
2302 break;
2303
2304- //MARK: stateJoinSessionFailedWaiting
2305 case stateJoinSessionFailedWaiting:
2306 // Joining a channel failed, either due to a failed channel name -> sip url lookup or an error from the join message.
2307 // Region crossings may leave this state and try the join again.
2308@@ -2368,24 +1901,22 @@ void LLVoiceClient::stateMachine()
2309 }
2310 break;
2311
2312- //MARK: stateJail
2313 case stateJail:
2314 // We have given up. Do nothing.
2315 break;
2316
2317+ case stateMicTuningNoLogin:
2318+ // *TODO: Implement me.
2319+ LL_WARNS("Voice") << "stateMicTuningNoLogin not handled" << LL_ENDL;
2320+ break;
2321 }
2322-
2323- if(mAudioSession && mAudioSession->mParticipantsChanged)
2324- {
2325- mAudioSession->mParticipantsChanged = false;
2326- mAudioSessionChanged = true;
2327- }
2328-
2329- if(mAudioSessionChanged)
2330+
2331+ if(mParticipantMapChanged)
2332 {
2333- mAudioSessionChanged = false;
2334- notifyParticipantObservers();
2335+ mParticipantMapChanged = false;
2336+ notifyObservers();
2337 }
2338+
2339 }
2340
2341 void LLVoiceClient::closeSocket(void)
2342@@ -2403,9 +1934,6 @@ void LLVoiceClient::loginSendMessage()
2343 << "<AccountName>" << mAccountName << "</AccountName>"
2344 << "<AccountPassword>" << mAccountPassword << "</AccountPassword>"
2345 << "<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>"
2346- << "<EnableBuddiesAndPresence>true</EnableBuddiesAndPresence>"
2347- << "<BuddyManagementMode>Application</BuddyManagementMode>"
2348- << "<ParticipantPropertyFrequency>5</ParticipantPropertyFrequency>"
2349 << "</Request>\n\n\n";
2350
2351 writeString(stream.str());
2352@@ -2413,10 +1941,7 @@ void LLVoiceClient::loginSendMessage()
2353
2354 void LLVoiceClient::logout()
2355 {
2356- // Ensure that we'll re-request provisioning before logging in again
2357- mAccountPassword.clear();
2358- mVoiceAccountServerURI.clear();
2359-
2360+ mAccountPassword = "";
2361 setState(stateLoggingOut);
2362 logoutSendMessage();
2363 }
2364@@ -2438,164 +1963,78 @@ void LLVoiceClient::logoutSendMessage()
2365 }
2366 }
2367
2368-void LLVoiceClient::accountListBlockRulesSendMessage()
2369+void LLVoiceClient::channelGetListSendMessage()
2370 {
2371- if(!mAccountHandle.empty())
2372- {
2373- std::ostringstream stream;
2374-
2375- LL_DEBUGS("Voice") << "requesting block rules" << LL_ENDL;
2376-
2377- stream
2378- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ListBlockRules.1\">"
2379- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
2380- << "</Request>"
2381- << "\n\n\n";
2382-
2383- writeString(stream.str());
2384- }
2385-}
2386-
2387-void LLVoiceClient::accountListAutoAcceptRulesSendMessage()
2388-{
2389- if(!mAccountHandle.empty())
2390- {
2391- std::ostringstream stream;
2392-
2393- LL_DEBUGS("Voice") << "requesting auto-accept rules" << LL_ENDL;
2394-
2395- stream
2396- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ListAutoAcceptRules.1\">"
2397- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
2398- << "</Request>"
2399- << "\n\n\n";
2400+ std::ostringstream stream;
2401+ stream
2402+ << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.ChannelGetList.1\">"
2403+ << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
2404+ << "</Request>\n\n\n";
2405
2406- writeString(stream.str());
2407- }
2408+ writeString(stream.str());
2409 }
2410
2411-void LLVoiceClient::sessionGroupCreateSendMessage()
2412+void LLVoiceClient::sessionCreateSendMessage()
2413 {
2414- if(!mAccountHandle.empty())
2415- {
2416- std::ostringstream stream;
2417-
2418- LL_DEBUGS("Voice") << "creating session group" << LL_ENDL;
2419+ LL_DEBUGS("Voice") << "requesting join: " << mNextSessionURI << LL_ENDL;
2420
2421- stream
2422- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.Create.1\">"
2423- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
2424- << "<Type>Normal</Type>"
2425- << "</Request>"
2426- << "\n\n\n";
2427-
2428- writeString(stream.str());
2429- }
2430-}
2431-
2432-void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)
2433-{
2434- LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
2435-
2436- session->mCreateInProgress = true;
2437- if(startAudio)
2438+ mSessionURI = mNextSessionURI;
2439+ mNonSpatialChannel = !mNextSessionSpatial;
2440+ mSessionResetOnClose = mNextSessionResetOnClose;
2441+ mNextSessionResetOnClose = false;
2442+ if(mNextSessionNoReconnect)
2443 {
2444- session->mMediaConnectInProgress = true;
2445+ // Clear the stashed URI so it can't reconnect
2446+ mNextSessionURI.clear();
2447 }
2448+ // Only p2p sessions are created with "no reconnect".
2449+ mSessionP2P = mNextSessionNoReconnect;
2450
2451 std::ostringstream stream;
2452 stream
2453- << "<Request requestId=\"" << session->mSIPURI << "\" action=\"Session.Create.1\">"
2454+ << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Create.1\">"
2455 << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
2456- << "<URI>" << session->mSIPURI << "</URI>";
2457+ << "<URI>" << mSessionURI << "</URI>";
2458
2459 static const std::string allowed_chars =
2460 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
2461 "0123456789"
2462 "-._~";
2463
2464- if(!session->mHash.empty())
2465+ if(!mNextSessionHash.empty())
2466 {
2467 stream
2468- << "<Password>" << LLURI::escape(session->mHash, allowed_chars) << "</Password>"
2469+ << "<Password>" << LLURI::escape(mNextSessionHash, allowed_chars) << "</Password>"
2470 << "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>";
2471 }
2472
2473 stream
2474- << "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
2475- << "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
2476 << "<Name>" << mChannelName << "</Name>"
2477 << "</Request>\n\n\n";
2478 writeString(stream.str());
2479 }
2480
2481-void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)
2482+void LLVoiceClient::sessionConnectSendMessage()
2483 {
2484- LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
2485-
2486- session->mCreateInProgress = true;
2487- if(startAudio)
2488- {
2489- session->mMediaConnectInProgress = true;
2490- }
2491-
2492- std::string password;
2493- if(!session->mHash.empty())
2494- {
2495- static const std::string allowed_chars =
2496- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
2497- "0123456789"
2498- "-._~"
2499- ;
2500- password = LLURI::escape(session->mHash, allowed_chars);
2501- }
2502-
2503- std::ostringstream stream;
2504- stream
2505- << "<Request requestId=\"" << session->mSIPURI << "\" action=\"SessionGroup.AddSession.1\">"
2506- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
2507- << "<URI>" << session->mSIPURI << "</URI>"
2508- << "<Name>" << mChannelName << "</Name>"
2509- << "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
2510- << "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
2511- << "<Password>" << password << "</Password>"
2512- << "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>"
2513- << "</Request>\n\n\n"
2514- ;
2515+ LL_DEBUGS("Voice") << "connecting to session handle: " << mNextSessionHandle << LL_ENDL;
2516
2517- writeString(stream.str());
2518-}
2519-
2520-void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
2521-{
2522- LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL;
2523-
2524- session->mMediaConnectInProgress = true;
2525+ mSessionHandle = mNextSessionHandle;
2526+ mSessionURI = mNextP2PSessionURI;
2527+ mNextSessionHandle.clear(); // never want to re-use these.
2528+ mNextP2PSessionURI.clear();
2529+ mNonSpatialChannel = !mNextSessionSpatial;
2530+ mSessionResetOnClose = mNextSessionResetOnClose;
2531+ mNextSessionResetOnClose = false;
2532+ // Joining by session ID is only used to answer p2p invitations, so we know this is a p2p session.
2533+ mSessionP2P = true;
2534
2535 std::ostringstream stream;
2536-
2537- stream
2538- << "<Request requestId=\"" << session->mHandle << "\" action=\"Session.MediaConnect.1\">"
2539- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
2540- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
2541- << "<Media>Audio</Media>"
2542- << "</Request>\n\n\n";
2543-
2544- writeString(stream.str());
2545-}
2546-
2547-void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
2548-{
2549- LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL;
2550
2551- std::ostringstream stream;
2552-
2553 stream
2554- << "<Request requestId=\"" << session->mHandle << "\" action=\"Session.TextConnect.1\">"
2555- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
2556- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
2557+ << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Connect.1\">"
2558+ << "<SessionHandle>" << mSessionHandle << "</SessionHandle>"
2559+ << "<AudioMedia>default</AudioMedia>"
2560 << "</Request>\n\n\n";
2561-
2562 writeString(stream.str());
2563 }
2564
2565@@ -2604,112 +2043,52 @@ void LLVoiceClient::sessionTerminate()
2566 mSessionTerminateRequested = true;
2567 }
2568
2569-void LLVoiceClient::requestRelog()
2570+void LLVoiceClient::sessionTerminateSendMessage()
2571 {
2572- mSessionTerminateRequested = true;
2573- mRelogRequested = true;
2574-}
2575+ LL_DEBUGS("Voice") << "leaving session: " << mSessionURI << LL_ENDL;
2576
2577-
2578-void LLVoiceClient::leaveAudioSession()
2579-{
2580- if(mAudioSession)
2581+ switch(getState())
2582 {
2583- LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL;
2584-
2585- switch(getState())
2586- {
2587- case stateNoChannel:
2588- // In this case, we want to pretend the join failed so our state machine doesn't get stuck.
2589- // Skip the join failed transition state so we don't send out error notifications.
2590- setState(stateJoinSessionFailedWaiting);
2591- break;
2592- case stateJoiningSession:
2593- case stateSessionJoined:
2594- case stateRunning:
2595- if(!mAudioSession->mHandle.empty())
2596- {
2597-
2598-#if RECORD_EVERYTHING
2599- // HACK: for testing only
2600- // Save looped recording
2601- std::string savepath("/tmp/vivoxrecording");
2602- {
2603- time_t now = time(NULL);
2604- const size_t BUF_SIZE = 64;
2605- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
2606-
2607- strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
2608- savepath += time_str;
2609- }
2610- recordingLoopSave(savepath);
2611-#endif
2612-
2613- sessionMediaDisconnectSendMessage(mAudioSession);
2614- setState(stateLeavingSession);
2615- }
2616- else
2617- {
2618- LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
2619- setState(stateSessionTerminated);
2620- }
2621- break;
2622- case stateJoinSessionFailed:
2623- case stateJoinSessionFailedWaiting:
2624+ case stateNoChannel:
2625+ // In this case, we want to pretend the join failed so our state machine doesn't get stuck.
2626+ // Skip the join failed transition state so we don't send out error notifications.
2627+ setState(stateJoinSessionFailedWaiting);
2628+ break;
2629+ case stateJoiningSession:
2630+ case stateSessionJoined:
2631+ case stateRunning:
2632+ if(!mSessionHandle.empty())
2633+ {
2634+ sessionTerminateByHandle(mSessionHandle);
2635+ setState(stateLeavingSession);
2636+ }
2637+ else
2638+ {
2639+ LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
2640 setState(stateSessionTerminated);
2641- break;
2642-
2643- default:
2644- LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
2645- break;
2646- }
2647- }
2648- else
2649- {
2650- LL_WARNS("Voice") << "called with no active session" << LL_ENDL;
2651- setState(stateSessionTerminated);
2652+ }
2653+ break;
2654+ case stateJoinSessionFailed:
2655+ case stateJoinSessionFailedWaiting:
2656+ setState(stateSessionTerminated);
2657+ break;
2658+
2659+ default:
2660+ LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
2661+ break;
2662 }
2663 }
2664
2665-void LLVoiceClient::sessionTerminateSendMessage(sessionState *session)
2666+void LLVoiceClient::sessionTerminateByHandle(std::string &sessionHandle)
2667 {
2668- std::ostringstream stream;
2669-
2670- LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL;
2671- stream
2672- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">"
2673- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
2674- << "</Request>\n\n\n";
2675-
2676- writeString(stream.str());
2677-}
2678+ LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << sessionHandle << LL_ENDL;
2679
2680-void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session)
2681-{
2682 std::ostringstream stream;
2683-
2684- LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL;
2685 stream
2686- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.MediaDisconnect.1\">"
2687- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
2688- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
2689- << "<Media>Audio</Media>"
2690- << "</Request>\n\n\n";
2691-
2692- writeString(stream.str());
2693-
2694-}
2695-
2696-void LLVoiceClient::sessionTextDisconnectSendMessage(sessionState *session)
2697-{
2698- std::ostringstream stream;
2699-
2700- LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL;
2701- stream
2702- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextDisconnect.1\">"
2703- << "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
2704- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
2705- << "</Request>\n\n\n";
2706+ << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Terminate.1\">"
2707+ << "<SessionHandle>" << sessionHandle << "</SessionHandle>"
2708+ << "</Request>"
2709+ << "\n\n\n";
2710
2711 writeString(stream.str());
2712 }
2713@@ -2736,12 +2115,14 @@ void LLVoiceClient::getRenderDevicesSendMessage()
2714
2715 void LLVoiceClient::clearCaptureDevices()
2716 {
2717+ // MBW -- XXX -- do something here
2718 LL_DEBUGS("Voice") << "called" << LL_ENDL;
2719 mCaptureDevices.clear();
2720 }
2721
2722 void LLVoiceClient::addCaptureDevice(const std::string& name)
2723 {
2724+ // MBW -- XXX -- do something here
2725 LL_DEBUGS("Voice") << name << LL_ENDL;
2726
2727 mCaptureDevices.push_back(name);
2728@@ -2773,13 +2154,15 @@ void LLVoiceClient::setCaptureDevice(const std::string& name)
2729 }
2730
2731 void LLVoiceClient::clearRenderDevices()
2732-{
2733+{
2734+ // MBW -- XXX -- do something here
2735 LL_DEBUGS("Voice") << "called" << LL_ENDL;
2736 mRenderDevices.clear();
2737 }
2738
2739 void LLVoiceClient::addRenderDevice(const std::string& name)
2740 {
2741+ // MBW -- XXX -- do something here
2742 LL_DEBUGS("Voice") << name << LL_ENDL;
2743 mRenderDevices.push_back(name);
2744 }
2745@@ -2891,22 +2274,29 @@ void LLVoiceClient::tuningCaptureStopSendMessage()
2746
2747 void LLVoiceClient::tuningSetMicVolume(float volume)
2748 {
2749- int scaled_volume = scale_mic_volume(volume);
2750-
2751- if(scaled_volume != mTuningMicVolume)
2752+ int scaledVolume = ((int)(volume * 100.0f)) - 100;
2753+ if(scaledVolume != mTuningMicVolume)
2754 {
2755- mTuningMicVolume = scaled_volume;
2756+ mTuningMicVolume = scaledVolume;
2757 mTuningMicVolumeDirty = true;
2758 }
2759 }
2760
2761 void LLVoiceClient::tuningSetSpeakerVolume(float volume)
2762 {
2763- int scaled_volume = scale_speaker_volume(volume);
2764+ // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
2765+ // Map it as follows: 0.0 -> -100, 0.5 -> 24, 1.0 -> 50
2766+
2767+ volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
2768+ int scaledVolume = 24; // offset scaledVolume by its default level
2769+ if(volume < 0.0f)
2770+ scaledVolume += ((int)(volume * 248.0f)); // (24 - (-100)) * 2
2771+ else
2772+ scaledVolume += ((int)(volume * 52.0f)); // (50 - 24) * 2
2773
2774- if(scaled_volume != mTuningSpeakerVolume)
2775+ if(scaledVolume != mTuningSpeakerVolume)
2776 {
2777- mTuningSpeakerVolume = scaled_volume;
2778+ mTuningSpeakerVolume = scaledVolume;
2779 mTuningSpeakerVolumeDirty = true;
2780 }
2781 }
2782@@ -2945,193 +2335,67 @@ void LLVoiceClient::daemonDied()
2783 // The daemon died, so the connection is gone. Reset everything and start over.
2784 LL_WARNS("Voice") << "Connection to vivox daemon lost. Resetting state."<< LL_ENDL;
2785
2786+ closeSocket();
2787+ removeAllParticipants();
2788+
2789 // Try to relaunch the daemon
2790- setState(stateDisableCleanup);
2791+ setState(stateDisabled);
2792 }
2793
2794 void LLVoiceClient::giveUp()
2795 {
2796 // All has failed. Clean up and stop trying.
2797 closeSocket();
2798- deleteAllSessions();
2799- deleteAllBuddies();
2800+ removeAllParticipants();
2801
2802 setState(stateJail);
2803 }
2804
2805-static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel)
2806-{
2807- F32 nat[3], nup[3], nl[3], nvel[3]; // the new at, up, left vectors and the new position and velocity
2808- F64 npos[3];
2809-
2810- // The original XML command was sent like this:
2811- /*
2812- << "<Position>"
2813- << "<X>" << pos[VX] << "</X>"
2814- << "<Y>" << pos[VZ] << "</Y>"
2815- << "<Z>" << pos[VY] << "</Z>"
2816- << "</Position>"
2817- << "<Velocity>"
2818- << "<X>" << mAvatarVelocity[VX] << "</X>"
2819- << "<Y>" << mAvatarVelocity[VZ] << "</Y>"
2820- << "<Z>" << mAvatarVelocity[VY] << "</Z>"
2821- << "</Velocity>"
2822- << "<AtOrientation>"
2823- << "<X>" << l.mV[VX] << "</X>"
2824- << "<Y>" << u.mV[VX] << "</Y>"
2825- << "<Z>" << a.mV[VX] << "</Z>"
2826- << "</AtOrientation>"
2827- << "<UpOrientation>"
2828- << "<X>" << l.mV[VZ] << "</X>"
2829- << "<Y>" << u.mV[VY] << "</Y>"
2830- << "<Z>" << a.mV[VZ] << "</Z>"
2831- << "</UpOrientation>"
2832- << "<LeftOrientation>"
2833- << "<X>" << l.mV [VY] << "</X>"
2834- << "<Y>" << u.mV [VZ] << "</Y>"
2835- << "<Z>" << a.mV [VY] << "</Z>"
2836- << "</LeftOrientation>";
2837- */
2838-
2839-#if 1
2840- // This was the original transform done when building the XML command
2841- nat[0] = left.mV[VX];
2842- nat[1] = up.mV[VX];
2843- nat[2] = at.mV[VX];
2844-
2845- nup[0] = left.mV[VZ];
2846- nup[1] = up.mV[VY];
2847- nup[2] = at.mV[VZ];
2848-
2849- nl[0] = left.mV[VY];
2850- nl[1] = up.mV[VZ];
2851- nl[2] = at.mV[VY];
2852-
2853- npos[0] = pos.mdV[VX];
2854- npos[1] = pos.mdV[VZ];
2855- npos[2] = pos.mdV[VY];
2856-
2857- nvel[0] = vel.mV[VX];
2858- nvel[1] = vel.mV[VZ];
2859- nvel[2] = vel.mV[VY];
2860-
2861- for(int i=0;i<3;++i) {
2862- at.mV[i] = nat[i];
2863- up.mV[i] = nup[i];
2864- left.mV[i] = nl[i];
2865- pos.mdV[i] = npos[i];
2866- }
2867-
2868- // This was the original transform done in the SDK
2869- nat[0] = at.mV[2];
2870- nat[1] = 0; // y component of at vector is always 0, this was up[2]
2871- nat[2] = -1 * left.mV[2];
2872-
2873- // We override whatever the application gives us
2874- nup[0] = 0; // x component of up vector is always 0
2875- nup[1] = 1; // y component of up vector is always 1
2876- nup[2] = 0; // z component of up vector is always 0
2877-
2878- nl[0] = at.mV[0];
2879- nl[1] = 0; // y component of left vector is always zero, this was up[0]
2880- nl[2] = -1 * left.mV[0];
2881-
2882- npos[2] = pos.mdV[2] * -1.0;
2883- npos[1] = pos.mdV[1];
2884- npos[0] = pos.mdV[0];
2885-
2886- for(int i=0;i<3;++i) {
2887- at.mV[i] = nat[i];
2888- up.mV[i] = nup[i];
2889- left.mV[i] = nl[i];
2890- pos.mdV[i] = npos[i];
2891- }
2892-#else
2893- // This is the compose of the two transforms (at least, that's what I'm trying for)
2894- nat[0] = at.mV[VX];
2895- nat[1] = 0; // y component of at vector is always 0, this was up[2]
2896- nat[2] = -1 * up.mV[VZ];
2897-
2898- // We override whatever the application gives us
2899- nup[0] = 0; // x component of up vector is always 0
2900- nup[1] = 1; // y component of up vector is always 1
2901- nup[2] = 0; // z component of up vector is always 0
2902-
2903- nl[0] = left.mV[VX];
2904- nl[1] = 0; // y component of left vector is always zero, this was up[0]
2905- nl[2] = -1 * left.mV[VY];
2906-
2907- npos[0] = pos.mdV[VX];
2908- npos[1] = pos.mdV[VZ];
2909- npos[2] = pos.mdV[VY] * -1.0;
2910-
2911- nvel[0] = vel.mV[VX];
2912- nvel[1] = vel.mV[VZ];
2913- nvel[2] = vel.mV[VY];
2914-
2915- for(int i=0;i<3;++i) {
2916- at.mV[i] = nat[i];
2917- up.mV[i] = nup[i];
2918- left.mV[i] = nl[i];
2919- pos.mdV[i] = npos[i];
2920- }
2921-
2922-#endif
2923-}
2924-
2925 void LLVoiceClient::sendPositionalUpdate(void)
2926 {
2927 std::ostringstream stream;
2928
2929 if(mSpatialCoordsDirty)
2930 {
2931- LLVector3 l, u, a, vel;
2932- LLVector3d pos;
2933-
2934- mSpatialCoordsDirty = false;
2935+ LLVector3 l, u, a;
2936
2937 // Always send both speaker and listener positions together.
2938 stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.Set3DPosition.1\">"
2939- << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>";
2940+ << "<SessionHandle>" << mSessionHandle << "</SessionHandle>";
2941
2942 stream << "<SpeakerPosition>";
2943
2944-// LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
2945 l = mAvatarRot.getLeftRow();
2946 u = mAvatarRot.getUpRow();
2947 a = mAvatarRot.getFwdRow();
2948- pos = mAvatarPosition;
2949- vel = mAvatarVelocity;
2950+
2951+ LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
2952
2953- // SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore.
2954- // The old transform is replicated by this function.
2955- oldSDKTransform(l, u, a, pos, vel);
2956-
2957 stream
2958 << "<Position>"
2959- << "<X>" << pos.mdV[VX] << "</X>"
2960- << "<Y>" << pos.mdV[VY] << "</Y>"
2961- << "<Z>" << pos.mdV[VZ] << "</Z>"
2962+ << "<X>" << mAvatarPosition[VX] << "</X>"
2963+ << "<Y>" << mAvatarPosition[VZ] << "</Y>"
2964+ << "<Z>" << mAvatarPosition[VY] << "</Z>"
2965 << "</Position>"
2966 << "<Velocity>"
2967- << "<X>" << vel.mV[VX] << "</X>"
2968- << "<Y>" << vel.mV[VY] << "</Y>"
2969- << "<Z>" << vel.mV[VZ] << "</Z>"
2970+ << "<X>" << mAvatarVelocity[VX] << "</X>"
2971+ << "<Y>" << mAvatarVelocity[VZ] << "</Y>"
2972+ << "<Z>" << mAvatarVelocity[VY] << "</Z>"
2973 << "</Velocity>"
2974 << "<AtOrientation>"
2975- << "<X>" << a.mV[VX] << "</X>"
2976- << "<Y>" << a.mV[VY] << "</Y>"
2977- << "<Z>" << a.mV[VZ] << "</Z>"
2978+ << "<X>" << l.mV[VX] << "</X>"
2979+ << "<Y>" << u.mV[VX] << "</Y>"
2980+ << "<Z>" << a.mV[VX] << "</Z>"
2981 << "</AtOrientation>"
2982 << "<UpOrientation>"
2983- << "<X>" << u.mV[VX] << "</X>"
2984+ << "<X>" << l.mV[VZ] << "</X>"
2985 << "<Y>" << u.mV[VY] << "</Y>"
2986- << "<Z>" << u.mV[VZ] << "</Z>"
2987+ << "<Z>" << a.mV[VZ] << "</Z>"
2988 << "</UpOrientation>"
2989 << "<LeftOrientation>"
2990- << "<X>" << l.mV [VX] << "</X>"
2991- << "<Y>" << l.mV [VY] << "</Y>"
2992- << "<Z>" << l.mV [VZ] << "</Z>"
2993+ << "<X>" << l.mV [VY] << "</X>"
2994+ << "<Y>" << u.mV [VZ] << "</Y>"
2995+ << "<Z>" << a.mV [VY] << "</Z>"
2996 << "</LeftOrientation>";
2997
2998 stream << "</SpeakerPosition>";
2999@@ -3167,158 +2431,43 @@ void LLVoiceClient::sendPositionalUpdate(void)
3000 l = earRot.getLeftRow();
3001 u = earRot.getUpRow();
3002 a = earRot.getFwdRow();
3003- pos = earPosition;
3004- vel = earVelocity;
3005
3006-// LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
3007-
3008- oldSDKTransform(l, u, a, pos, vel);
3009-
3010+ LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
3011+
3012 stream
3013 << "<Position>"
3014- << "<X>" << pos.mdV[VX] << "</X>"
3015- << "<Y>" << pos.mdV[VY] << "</Y>"
3016- << "<Z>" << pos.mdV[VZ] << "</Z>"
3017+ << "<X>" << earPosition[VX] << "</X>"
3018+ << "<Y>" << earPosition[VZ] << "</Y>"
3019+ << "<Z>" << earPosition[VY] << "</Z>"
3020 << "</Position>"
3021 << "<Velocity>"
3022- << "<X>" << vel.mV[VX] << "</X>"
3023- << "<Y>" << vel.mV[VY] << "</Y>"
3024- << "<Z>" << vel.mV[VZ] << "</Z>"
3025+ << "<X>" << earVelocity[VX] << "</X>"
3026+ << "<Y>" << earVelocity[VZ] << "</Y>"
3027+ << "<Z>" << earVelocity[VY] << "</Z>"
3028 << "</Velocity>"
3029 << "<AtOrientation>"
3030- << "<X>" << a.mV[VX] << "</X>"
3031- << "<Y>" << a.mV[VY] << "</Y>"
3032- << "<Z>" << a.mV[VZ] << "</Z>"
3033+ << "<X>" << l.mV[VX] << "</X>"
3034+ << "<Y>" << u.mV[VX] << "</Y>"
3035+ << "<Z>" << a.mV[VX] << "</Z>"
3036 << "</AtOrientation>"
3037 << "<UpOrientation>"
3038- << "<X>" << u.mV[VX] << "</X>"
3039+ << "<X>" << l.mV[VZ] << "</X>"
3040 << "<Y>" << u.mV[VY] << "</Y>"
3041- << "<Z>" << u.mV[VZ] << "</Z>"
3042+ << "<Z>" << a.mV[VZ] << "</Z>"
3043 << "</UpOrientation>"
3044 << "<LeftOrientation>"
3045- << "<X>" << l.mV [VX] << "</X>"
3046- << "<Y>" << l.mV [VY] << "</Y>"
3047- << "<Z>" << l.mV [VZ] << "</Z>"
3048+ << "<X>" << l.mV [VY] << "</X>"
3049+ << "<Y>" << u.mV [VZ] << "</Y>"
3050+ << "<Z>" << a.mV [VY] << "</Z>"
3051 << "</LeftOrientation>";
3052
3053-
3054 stream << "</ListenerPosition>";
3055
3056 stream << "</Request>\n\n\n";
3057 }
3058-
3059- if(mAudioSession && mAudioSession->mVolumeDirty)
3060- {
3061- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
3062-
3063- mAudioSession->mVolumeDirty = false;
3064-
3065- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
3066- {
3067- participantState *p = iter->second;
3068-
3069- if(p->mVolumeDirty)
3070- {
3071- // Can't set volume/mute for yourself
3072- if(!p->mIsSelf)
3073- {
3074- int volume = p->mUserVolume;
3075- bool mute = p->mOnMuteList;
3076-
3077- // SLIM SDK: scale volume from 0-400 (with 100 as "normal") to 0-100 (with 56 as "normal")
3078- if(volume < 100)
3079- volume = (volume * 56) / 100;
3080- else
3081- volume = (((volume - 100) * (100 - 56)) / 300) + 56;
3082-
3083- if(mute)
3084- {
3085- // SetParticipantMuteForMe doesn't work in p2p sessions.
3086- // If we want the user to be muted, set their volume to 0 as well.
3087- // This isn't perfect, but it will at least reduce their volume to a minimum.
3088- volume = 0;
3089- }
3090-
3091- if(volume == 0)
3092- mute = true;
3093-
3094- LL_DEBUGS("Voice") << "Setting volume/mute for avatar " << p->mAvatarID << " to " << volume << (mute?"/true":"/false") << LL_ENDL;
3095-
3096- // SLIM SDK: Send both volume and mute commands.
3097-
3098- // Send a "volume for me" command for the user.
3099- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantVolumeForMe.1\">"
3100- << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
3101- << "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
3102- << "<Volume>" << volume << "</Volume>"
3103- << "</Request>\n\n\n";
3104-
3105- // Send a "mute for me" command for the user
3106- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantMuteForMe.1\">"
3107- << "<SessionHandle>" << getAudioSessionHandle() << "</SessionHandle>"
3108- << "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
3109- << "<Mute>" << (mute?"1":"0") << "</Mute>"
3110- << "</Request>\n\n\n";
3111- }
3112-
3113- p->mVolumeDirty = false;
3114- }
3115- }
3116- }
3117-
3118- buildLocalAudioUpdates(stream);
3119-
3120- if(!stream.str().empty())
3121- {
3122- writeString(stream.str());
3123- }
3124-
3125- // Friends list updates can be huge, especially on the first voice login of an account with lots of friends.
3126- // Batching them all together can choke SLVoice, so send them in separate writes.
3127- sendFriendsListUpdates();
3128-}
3129-
3130-void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
3131-{
3132- if(mCaptureDeviceDirty)
3133- {
3134- LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
3135-
3136- stream
3137- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">"
3138- << "<CaptureDeviceSpecifier>" << mCaptureDevice << "</CaptureDeviceSpecifier>"
3139- << "</Request>"
3140- << "\n\n\n";
3141-
3142- mCaptureDeviceDirty = false;
3143- }
3144-}
3145-
3146-void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
3147-{
3148- if(mRenderDeviceDirty)
3149- {
3150- LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
3151-
3152- stream
3153- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetRenderDevice.1\">"
3154- << "<RenderDeviceSpecifier>" << mRenderDevice << "</RenderDeviceSpecifier>"
3155- << "</Request>"
3156- << "\n\n\n";
3157- mRenderDeviceDirty = false;
3158- }
3159-}
3160-
3161-void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
3162-{
3163- buildSetCaptureDevice(stream);
3164-
3165- buildSetRenderDevice(stream);
3166
3167 if(mPTTDirty)
3168 {
3169- mPTTDirty = false;
3170-
3171 // Send a local mute command.
3172 // NOTE that the state of "PTT" is the inverse of "local mute".
3173 // (i.e. when PTT is true, we send a mute command with "false", and vice versa)
3174@@ -3329,337 +2478,119 @@ void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
3175 << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
3176 << "<Value>" << (mPTT?"false":"true") << "</Value>"
3177 << "</Request>\n\n\n";
3178-
3179+
3180 }
3181+
3182+ if(mVolumeDirty)
3183+ {
3184+ participantMap::iterator iter = mParticipantMap.begin();
3185+
3186+ for(; iter != mParticipantMap.end(); iter++)
3187+ {
3188+ participantState *p = iter->second;
3189+
3190+ if(p->mVolumeDirty)
3191+ {
3192+ int volume = p->mOnMuteList?0:p->mUserVolume;
3193+
3194+ LL_INFOS("Voice") << "Setting volume for avatar " << p->mAvatarID << " to " << volume << LL_ENDL;
3195+
3196+ // Send a mute/unumte command for the user (actually "volume for me").
3197+ stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetParticipantVolumeForMe.1\">"
3198+ << "<SessionHandle>" << mSessionHandle << "</SessionHandle>"
3199+ << "<ParticipantURI>" << p->mURI << "</ParticipantURI>"
3200+ << "<Volume>" << volume << "</Volume>"
3201+ << "</Request>\n\n\n";
3202
3203+ p->mVolumeDirty = false;
3204+ }
3205+ }
3206+ }
3207+
3208 if(mSpeakerMuteDirty)
3209 {
3210- const char *muteval = ((mSpeakerVolume == 0)?"true":"false");
3211-
3212- mSpeakerMuteDirty = false;
3213-
3214+ const char *muteval = ((mSpeakerVolume == -100)?"true":"false");
3215 LL_INFOS("Voice") << "Setting speaker mute to " << muteval << LL_ENDL;
3216
3217 stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalSpeaker.1\">"
3218 << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
3219 << "<Value>" << muteval << "</Value>"
3220- << "</Request>\n\n\n";
3221-
3222+ << "</Request>\n\n\n";
3223 }
3224
3225 if(mSpeakerVolumeDirty)
3226 {
3227- mSpeakerVolumeDirty = false;
3228-
3229 LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume << LL_ENDL;
3230
3231 stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalSpeakerVolume.1\">"
3232 << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
3233 << "<Value>" << mSpeakerVolume << "</Value>"
3234- << "</Request>\n\n\n";
3235-
3236+ << "</Request>\n\n\n";
3237 }
3238
3239 if(mMicVolumeDirty)
3240 {
3241- mMicVolumeDirty = false;
3242-
3243 LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume << LL_ENDL;
3244
3245 stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.SetLocalMicVolume.1\">"
3246 << "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
3247 << "<Value>" << mMicVolume << "</Value>"
3248- << "</Request>\n\n\n";
3249+ << "</Request>\n\n\n";
3250 }
3251
3252
3253-}
3254-
3255-void LLVoiceClient::checkFriend(const LLUUID& id)
3256-{
3257- std::string name;
3258- buddyListEntry *buddy = findBuddy(id);
3259-
3260- // Make sure we don't add a name before it's been looked up.
3261- if(gCacheName->getFullName(id, name))
3262+ // MBW -- XXX -- Maybe check to make sure the capture/render devices are in the current list here?
3263+ if(mCaptureDeviceDirty)
3264 {
3265-
3266- const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
3267- bool canSeeMeOnline = false;
3268- if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
3269- canSeeMeOnline = true;
3270-
3271- // When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary.
3272-
3273- if(buddy)
3274- {
3275- // This buddy is already in both lists.
3276-
3277- if(name != buddy->mDisplayName)
3278- {
3279- // The buddy is in the list with the wrong name. Update it with the correct name.
3280- LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
3281- buddy->mDisplayName = name;
3282- buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
3283- }
3284- }
3285- else
3286- {
3287- // This buddy was not in the vivox list, needs to be added.
3288- buddy = addBuddy(sipURIFromID(id), name);
3289- buddy->mUUID = id;
3290- }
3291-
3292- // In all the above cases, the buddy is in the SL friends list (which is how we got here).
3293- buddy->mInSLFriends = true;
3294- buddy->mCanSeeMeOnline = canSeeMeOnline;
3295- buddy->mNameResolved = true;
3296-
3297+ buildSetCaptureDevice(stream);
3298 }
3299- else
3300+
3301+ if(mRenderDeviceDirty)
3302 {
3303- // This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has.
3304- if(buddy)
3305- {
3306- buddy->mNameResolved = false;
3307- }
3308-
3309- // Initiate a lookup.
3310- // The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
3311- lookupName(id);
3312+ buildSetRenderDevice(stream);
3313 }
3314-}
3315-
3316-void LLVoiceClient::clearAllLists()
3317-{
3318- // FOR TESTING ONLY
3319
3320- // This will send the necessary commands to delete ALL buddies, autoaccept rules, and block rules SLVoice tells us about.
3321- buddyListMap::iterator buddy_it;
3322- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
3323+ mSpatialCoordsDirty = false;
3324+ mPTTDirty = false;
3325+ mVolumeDirty = false;
3326+ mSpeakerVolumeDirty = false;
3327+ mMicVolumeDirty = false;
3328+ mSpeakerMuteDirty = false;
3329+ mCaptureDeviceDirty = false;
3330+ mRenderDeviceDirty = false;
3331+
3332+ if(!stream.str().empty())
3333 {
3334- buddyListEntry *buddy = buddy_it->second;
3335- buddy_it++;
3336-
3337- std::ostringstream stream;
3338-
3339- if(buddy->mInVivoxBuddies)
3340- {
3341- // delete this entry from the vivox buddy list
3342- buddy->mInVivoxBuddies = false;
3343- LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
3344- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddyDelete.1\">"
3345- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3346- << "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
3347- << "</Request>\n\n\n";
3348- }
3349-
3350- if(buddy->mHasBlockListEntry)
3351- {
3352- // Delete the associated block list entry (so the block list doesn't fill up with junk)
3353- buddy->mHasBlockListEntry = false;
3354- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
3355- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3356- << "<BlockMask>" << buddy->mURI << "</BlockMask>"
3357- << "</Request>\n\n\n";
3358- }
3359- if(buddy->mHasAutoAcceptListEntry)
3360- {
3361- // Delete the associated auto-accept list entry (so the auto-accept list doesn't fill up with junk)
3362- buddy->mHasAutoAcceptListEntry = false;
3363- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
3364- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3365- << "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
3366- << "</Request>\n\n\n";
3367- }
3368-
3369 writeString(stream.str());
3370-
3371 }
3372 }
3373
3374-void LLVoiceClient::sendFriendsListUpdates()
3375+void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
3376 {
3377- if(mBuddyListMapPopulated && mBlockRulesListReceived && mAutoAcceptRulesListReceived && mFriendsListDirty)
3378- {
3379- mFriendsListDirty = false;
3380-
3381- if(0)
3382- {
3383- // FOR TESTING ONLY -- clear all buddy list, block list, and auto-accept list entries.
3384- clearAllLists();
3385- return;
3386- }
3387-
3388- LL_INFOS("Voice") << "Checking vivox buddy list against friends list..." << LL_ENDL;
3389-
3390- buddyListMap::iterator buddy_it;
3391- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
3392- {
3393- // reset the temp flags in the local buddy list
3394- buddy_it->second->mInSLFriends = false;
3395- }
3396-
3397- // correlate with the friends list
3398- {
3399- LLCollectAllBuddies collect;
3400- LLAvatarTracker::instance().applyFunctor(collect);
3401- LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin();
3402- LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
3403-
3404- for ( ; it != end; ++it)
3405- {
3406- checkFriend(it->second);
3407- }
3408- it = collect.mOffline.begin();
3409- end = collect.mOffline.end();
3410- for ( ; it != end; ++it)
3411- {
3412- checkFriend(it->second);
3413- }
3414- }
3415-
3416- LL_INFOS("Voice") << "Sending friend list updates..." << LL_ENDL;
3417-
3418- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
3419- {
3420- buddyListEntry *buddy = buddy_it->second;
3421- buddy_it++;
3422-
3423- // Ignore entries that aren't resolved yet.
3424- if(buddy->mNameResolved)
3425- {
3426- std::ostringstream stream;
3427-
3428- if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
3429- {
3430- if(mNumberOfAliases > 0)
3431- {
3432- // Add (or update) this entry in the vivox buddy list
3433- buddy->mInVivoxBuddies = true;
3434- buddy->mNeedsNameUpdate = false;
3435- LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
3436- stream
3437- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
3438- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3439- << "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
3440- << "<DisplayName>" << buddy->mDisplayName << "</DisplayName>"
3441- << "<BuddyData></BuddyData>" // Without this, SLVoice doesn't seem to parse the command.
3442- << "<GroupID>0</GroupID>"
3443- << "</Request>\n\n\n";
3444- }
3445- }
3446- else if(!buddy->mInSLFriends)
3447- {
3448- // This entry no longer exists in your SL friends list. Remove all traces of it from the Vivox buddy list.
3449- if(buddy->mInVivoxBuddies)
3450- {
3451- // delete this entry from the vivox buddy list
3452- buddy->mInVivoxBuddies = false;
3453- LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
3454- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddyDelete.1\">"
3455- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3456- << "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
3457- << "</Request>\n\n\n";
3458- }
3459-
3460- if(buddy->mHasBlockListEntry)
3461- {
3462- // Delete the associated block list entry, if any
3463- buddy->mHasBlockListEntry = false;
3464- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
3465- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3466- << "<BlockMask>" << buddy->mURI << "</BlockMask>"
3467- << "</Request>\n\n\n";
3468- }
3469- if(buddy->mHasAutoAcceptListEntry)
3470- {
3471- // Delete the associated auto-accept list entry, if any
3472- buddy->mHasAutoAcceptListEntry = false;
3473- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
3474- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3475- << "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
3476- << "</Request>\n\n\n";
3477- }
3478- }
3479-
3480- if(buddy->mInSLFriends)
3481- {
3482-
3483- if(buddy->mCanSeeMeOnline)
3484- {
3485- // Buddy should not be blocked.
3486-
3487- // If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
3488-
3489- // If the buddy has a block list entry, delete it.
3490- if(buddy->mHasBlockListEntry)
3491- {
3492- buddy->mHasBlockListEntry = false;
3493- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteBlockRule.1\">"
3494- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3495- << "<BlockMask>" << buddy->mURI << "</BlockMask>"
3496- << "</Request>\n\n\n";
3497-
3498-
3499- // If we just deleted a block list entry, add an auto-accept entry.
3500- if(!buddy->mHasAutoAcceptListEntry)
3501- {
3502- buddy->mHasAutoAcceptListEntry = true;
3503- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.CreateAutoAcceptRule.1\">"
3504- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3505- << "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
3506- << "<AutoAddAsBuddy>0</AutoAddAsBuddy>"
3507- << "</Request>\n\n\n";
3508- }
3509- }
3510- }
3511- else
3512- {
3513- // Buddy should be blocked.
3514-
3515- // If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
3516-
3517- // If this buddy has an autoaccept entry, delete it
3518- if(buddy->mHasAutoAcceptListEntry)
3519- {
3520- buddy->mHasAutoAcceptListEntry = false;
3521- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.DeleteAutoAcceptRule.1\">"
3522- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3523- << "<AutoAcceptMask>" << buddy->mURI << "</AutoAcceptMask>"
3524- << "</Request>\n\n\n";
3525-
3526- // If we just deleted an auto-accept entry, add a block list entry.
3527- if(!buddy->mHasBlockListEntry)
3528- {
3529- buddy->mHasBlockListEntry = true;
3530- stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.CreateBlockRule.1\">"
3531- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
3532- << "<BlockMask>" << buddy->mURI << "</BlockMask>"
3533- << "<PresenceOnly>1</PresenceOnly>"
3534- << "</Request>\n\n\n";
3535- }
3536- }
3537- }
3538+ LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
3539+
3540+ stream
3541+ << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetCaptureDevice.1\">"
3542+ << "<CaptureDeviceSpecifier>" << mCaptureDevice << "</CaptureDeviceSpecifier>"
3543+ << "</Request>"
3544+ << "\n\n\n";
3545+}
3546
3547- if(!buddy->mInSLFriends && !buddy->mInVivoxBuddies)
3548- {
3549- // Delete this entry from the local buddy list. This should NOT invalidate the iterator,
3550- // since it has already been incremented to the next entry.
3551- deleteBuddy(buddy->mURI);
3552- }
3553+void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
3554+{
3555+ LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
3556
3557- }
3558- writeString(stream.str());
3559- }
3560- }
3561- }
3562+ stream
3563+ << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetRenderDevice.1\">"
3564+ << "<RenderDeviceSpecifier>" << mRenderDevice << "</RenderDeviceSpecifier>"
3565+ << "</Request>"
3566+ << "\n\n\n";
3567 }
3568
3569 /////////////////////////////
3570 // Response/Event handlers
3571
3572-void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID)
3573+void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle)
3574 {
3575 if(statusCode != 0)
3576 {
3577@@ -3669,7 +2600,6 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
3578 else
3579 {
3580 // Connector created, move forward.
3581- LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
3582 mConnectorHandle = connectorHandle;
3583 if(getState() == stateConnectorStarting)
3584 {
3585@@ -3678,7 +2608,7 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
3586 }
3587 }
3588
3589-void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
3590+void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle)
3591 {
3592 LL_DEBUGS("Voice") << "Account.Login response (" << statusCode << "): " << statusString << LL_ENDL;
3593
3594@@ -3699,8 +2629,7 @@ void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std
3595 {
3596 // Login succeeded, move forward.
3597 mAccountHandle = accountHandle;
3598- mNumberOfAliases = numberOfAliases;
3599- // This needs to wait until the AccountLoginStateChangeEvent is received.
3600+ // MBW -- XXX -- This needs to wait until the LoginStateChangeEvent is received.
3601 // if(getState() == stateLoggingIn)
3602 // {
3603 // setState(stateLoggedIn);
3604@@ -3708,91 +2637,106 @@ void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std
3605 }
3606 }
3607
3608-void LLVoiceClient::sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
3609-{
3610- sessionState *session = findSessionBeingCreatedByURI(requestId);
3611-
3612- if(session)
3613- {
3614- session->mCreateInProgress = false;
3615- }
3616-
3617+void LLVoiceClient::channelGetListResponse(int statusCode, std::string &statusString)
3618+{
3619 if(statusCode != 0)
3620 {
3621- LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
3622- if(session)
3623- {
3624- session->mErrorStatusCode = statusCode;
3625- session->mErrorStatusString = statusString;
3626- if(session == mAudioSession)
3627- {
3628- setState(stateJoinSessionFailed);
3629- }
3630- else
3631- {
3632- reapSession(session);
3633- }
3634- }
3635+ LL_WARNS("Voice") << "Account.ChannelGetList response failure: " << statusString << LL_ENDL;
3636+ switchChannel();
3637 }
3638 else
3639 {
3640- LL_INFOS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
3641- if(session)
3642+ // Got the channel list, try to do a lookup.
3643+ std::string uri = findChannelURI(mChannelName);
3644+ if(uri.empty())
3645+ {
3646+ // Lookup failed, can't join a channel for this area.
3647+ LL_INFOS("Voice") << "failed to map channel name: " << mChannelName << LL_ENDL;
3648+ }
3649+ else
3650 {
3651- setSessionHandle(session, sessionHandle);
3652+ // We have a sip URL for this area.
3653+ LL_INFOS("Voice") << "mapped channel " << mChannelName << " to URI "<< uri << LL_ENDL;
3654 }
3655+
3656+ // switchChannel with an empty uri string will do the right thing (leave channel and not rejoin)
3657+ switchChannel(uri);
3658 }
3659 }
3660
3661-void LLVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
3662+void LLVoiceClient::sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle)
3663 {
3664- sessionState *session = findSessionBeingCreatedByURI(requestId);
3665-
3666- if(session)
3667- {
3668- session->mCreateInProgress = false;
3669- }
3670-
3671 if(statusCode != 0)
3672 {
3673- LL_WARNS("Voice") << "SessionGroup.AddSession response failure (" << statusCode << "): " << statusString << LL_ENDL;
3674- if(session)
3675+ LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
3676+// if(statusCode == 1015)
3677+// {
3678+// if(getState() == stateJoiningSession)
3679+// {
3680+// // this happened during a real join. Going to sessionTerminated should cause a retry in appropriate cases.
3681+// LL_WARNS("Voice") << "session handle \"" << sessionHandle << "\", mSessionStateEventHandle \"" << mSessionStateEventHandle << "\""<< LL_ENDL;
3682+// if(!sessionHandle.empty())
3683+// {
3684+// // This session is bad. Terminate it.
3685+// mSessionHandle = sessionHandle;
3686+// sessionTerminateByHandle(sessionHandle);
3687+// setState(stateLeavingSession);
3688+// }
3689+// else if(!mSessionStateEventHandle.empty())
3690+// {
3691+// mSessionHandle = mSessionStateEventHandle;
3692+// sessionTerminateByHandle(mSessionStateEventHandle);
3693+// setState(stateLeavingSession);
3694+// }
3695+// else
3696+// {
3697+// setState(stateSessionTerminated);
3698+// }
3699+// }
3700+// else
3701+// {
3702+// // We didn't think we were in the middle of a join. Don't change state.
3703+// LL_WARNS("Voice") << "Not in stateJoiningSession, ignoring" << LL_ENDL;
3704+// }
3705+// }
3706+// else
3707 {
3708- session->mErrorStatusCode = statusCode;
3709- session->mErrorStatusString = statusString;
3710- if(session == mAudioSession)
3711- {
3712- setState(stateJoinSessionFailed);
3713- }
3714- else
3715- {
3716- reapSession(session);
3717- }
3718+ mVivoxErrorStatusCode = statusCode;
3719+ mVivoxErrorStatusString = statusString;
3720+ setState(stateJoinSessionFailed);
3721 }
3722 }
3723 else
3724 {
3725- LL_DEBUGS("Voice") << "SessionGroup.AddSession response received (success), session handle is " << sessionHandle << LL_ENDL;
3726- if(session)
3727+ LL_DEBUGS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
3728+ if(getState() == stateJoiningSession)
3729 {
3730- setSessionHandle(session, sessionHandle);
3731+ // This is also grabbed in the SessionStateChangeEvent handler, but it might be useful to have it early...
3732+ mSessionHandle = sessionHandle;
3733+ }
3734+ else
3735+ {
3736+ // We should never get a session.create response in any state except stateJoiningSession. Things are out of sync. Kill this session.
3737+ sessionTerminateByHandle(sessionHandle);
3738 }
3739 }
3740 }
3741
3742-void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString)
3743+void LLVoiceClient::sessionConnectResponse(int statusCode, std::string &statusString)
3744 {
3745- sessionState *session = findSession(requestId);
3746 if(statusCode != 0)
3747 {
3748 LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL;
3749- if(session)
3750+// if(statusCode == 1015)
3751+// {
3752+// LL_WARNS("Voice") << "terminating existing session" << LL_ENDL;
3753+// sessionTerminate();
3754+// }
3755+// else
3756 {
3757- session->mMediaConnectInProgress = false;
3758- session->mErrorStatusCode = statusCode;
3759- session->mErrorStatusString = statusString;
3760- if(session == mAudioSession)
3761- setState(stateJoinSessionFailed);
3762+ mVivoxErrorStatusCode = statusCode;
3763+ mVivoxErrorStatusString = statusString;
3764+ setState(stateJoinSessionFailed);
3765 }
3766 }
3767 else
3768@@ -3801,12 +2745,27 @@ void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCod
3769 }
3770 }
3771
3772+void LLVoiceClient::sessionTerminateResponse(int statusCode, std::string &statusString)
3773+{
3774+ if(statusCode != 0)
3775+ {
3776+ LL_WARNS("Voice") << "Session.Terminate response failure: (" << statusCode << "): " << statusString << LL_ENDL;
3777+ if(getState() == stateLeavingSession)
3778+ {
3779+ // This is probably "(404): Server reporting Failure. Not a member of this conference."
3780+ // Do this so we don't get stuck.
3781+ setState(stateSessionTerminated);
3782+ }
3783+ }
3784+
3785+}
3786+
3787 void LLVoiceClient::logoutResponse(int statusCode, std::string &statusString)
3788 {
3789 if(statusCode != 0)
3790 {
3791 LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL;
3792- // Should this ever fail? do we care if it does?
3793+ // MBW -- XXX -- Should this ever fail? do we care if it does?
3794 }
3795
3796 if(getState() == stateLoggingOut)
3797@@ -3820,7 +2779,7 @@ void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statu
3798 if(statusCode != 0)
3799 {
3800 LL_WARNS("Voice") << "Connector.InitiateShutdown response failure: " << statusString << LL_ENDL;
3801- // Should this ever fail? do we care if it does?
3802+ // MBW -- XXX -- Should this ever fail? do we care if it does?
3803 }
3804
3805 mConnected = false;
3806@@ -3831,277 +2790,109 @@ void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statu
3807 }
3808 }
3809
3810-void LLVoiceClient::sessionAddedEvent(
3811+void LLVoiceClient::sessionStateChangeEvent(
3812 std::string &uriString,
3813- std::string &alias,
3814- std::string &sessionHandle,
3815- std::string &sessionGroupHandle,
3816+ int statusCode,
3817+ std::string &statusString,
3818+ std::string &sessionHandle,
3819+ int state,
3820 bool isChannel,
3821- bool incoming,
3822- std::string &nameString,
3823- std::string &applicationString)
3824+ std::string &nameString)
3825 {
3826- sessionState *session = NULL;
3827-
3828- LL_INFOS("Voice") << "session " << uriString << ", alias " << alias << ", name " << nameString << " handle " << sessionHandle << LL_ENDL;
3829-
3830- session = addSession(uriString, sessionHandle);
3831- if(session)
3832+ switch(state)
3833 {
3834- session->mGroupHandle = sessionGroupHandle;
3835- session->mIsChannel = isChannel;
3836- session->mIncoming = incoming;
3837- session->mAlias = alias;
3838-
3839- // Generate a caller UUID -- don't need to do this for channels
3840- if(!session->mIsChannel)
3841- {
3842- if(IDFromName(session->mSIPURI, session->mCallerID))
3843+ case 4: // I see this when joining the session
3844+ LL_INFOS("Voice") << "joined session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << LL_ENDL;
3845+
3846+ // Session create succeeded, move forward.
3847+ mSessionStateEventHandle = sessionHandle;
3848+ mSessionStateEventURI = uriString;
3849+ if(sessionHandle == mSessionHandle)
3850 {
3851- // Normal URI(base64-encoded UUID)
3852+ // This is the session we're joining.
3853+ if(getState() == stateJoiningSession)
3854+ {
3855+ setState(stateSessionJoined);
3856+ //RN: the uriString being returned by vivox here is actually your account uri, not the channel
3857+ // you are attempting to join, so ignore it
3858+ //LL_DEBUGS("Voice") << "received URI " << uriString << "(previously " << mSessionURI << ")" << LL_ENDL;
3859+ //mSessionURI = uriString;
3860+ }
3861 }
3862- else if(!session->mAlias.empty() && IDFromName(session->mAlias, session->mCallerID))
3863+ else if(sessionHandle == mNextSessionHandle)
3864 {
3865- // Wrong URI, but an alias is available. Stash the incoming URI as an alternate
3866- session->mAlternateSIPURI = session->mSIPURI;
3867-
3868- // and generate a proper URI from the ID.
3869- setSessionURI(session, sipURIFromID(session->mCallerID));
3870+// LL_DEBUGS("Voice") << "received URI " << uriString << ", name " << nameString << " for next session (handle " << mNextSessionHandle << ")" << LL_ENDL;
3871 }
3872 else
3873 {
3874- LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL;
3875- setUUIDFromStringHash(session->mCallerID, session->mSIPURI);
3876- session->mSynthesizedCallerID = true;
3877-
3878- // Can't look up the name in this case -- we have to extract it from the URI.
3879- std::string namePortion = nameFromsipURI(session->mSIPURI);
3880- if(namePortion.empty())
3881- {
3882- // Didn't seem to be a SIP URI, just use the whole provided name.
3883- namePortion = nameString;
3884- }
3885-
3886- // Some incoming names may be separated with an underscore instead of a space. Fix this.
3887- LLStringUtil::replaceChar(namePortion, '_', ' ');
3888-
3889- // Act like we just finished resolving the name (this stores it in all the right places)
3890- avatarNameResolved(session->mCallerID, namePortion);
3891+ LL_WARNS("Voice") << "joining unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << LL_ENDL;
3892+ // MBW -- XXX -- Should we send a Session.Terminate here?
3893 }
3894-
3895- LL_INFOS("Voice") << "caller ID: " << session->mCallerID << LL_ENDL;
3896-
3897- if(!session->mSynthesizedCallerID)
3898- {
3899- // If we got here, we don't have a proper name. Initiate a lookup.
3900- lookupName(session->mCallerID);
3901- }
3902- }
3903- }
3904-}
3905-
3906-void LLVoiceClient::sessionGroupAddedEvent(std::string &sessionGroupHandle)
3907-{
3908- LL_DEBUGS("Voice") << "handle " << sessionGroupHandle << LL_ENDL;
3909-
3910-#if USE_SESSION_GROUPS
3911- if(mMainSessionGroupHandle.empty())
3912- {
3913- // This is the first (i.e. "main") session group. Save its handle.
3914- mMainSessionGroupHandle = sessionGroupHandle;
3915- }
3916- else
3917- {
3918- LL_DEBUGS("Voice") << "Already had a session group handle " << mMainSessionGroupHandle << LL_ENDL;
3919- }
3920-#endif
3921-}
3922-
3923-void LLVoiceClient::joinedAudioSession(sessionState *session)
3924-{
3925- if(mAudioSession != session)
3926- {
3927- sessionState *oldSession = mAudioSession;
3928-
3929- mAudioSession = session;
3930- mAudioSessionChanged = true;
3931-
3932- // The old session may now need to be deleted.
3933- reapSession(oldSession);
3934- }
3935-
3936- // This is the session we're joining.
3937- if(getState() == stateJoiningSession)
3938- {
3939- setState(stateSessionJoined);
3940-
3941- // SLIM SDK: we don't always receive a participant state change for ourselves when joining a channel now.
3942- // Add the current user as a participant here.
3943- participantState *participant = session->addParticipant(sipURIFromName(mAccountName));
3944- if(participant)
3945- {
3946- participant->mIsSelf = true;
3947- lookupName(participant->mAvatarID);
3948+
3949+ break;
3950+ case 5: // I see this when leaving the session
3951+ LL_INFOS("Voice") << "left session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << LL_ENDL;
3952
3953- LL_INFOS("Voice") << "added self as participant \"" << participant->mAccountName
3954- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
3955- }
3956-
3957- if(!session->mIsChannel)
3958- {
3959- // this is a p2p session. Make sure the other end is added as a participant.
3960- participantState *participant = session->addParticipant(session->mSIPURI);
3961- if(participant)
3962+ // Set the session handle to the empty string. If we get back to stateJoiningSession, we'll want to wait for the new session handle.
3963+ if(sessionHandle == mSessionHandle)
3964 {
3965- if(participant->mAvatarIDValid)
3966+ // MBW -- XXX -- I think this is no longer necessary, now that we've got mNextSessionURI/mNextSessionHandle
3967+ // mSessionURI.clear();
3968+ // clear the session handle here just for sanity.
3969+ mSessionHandle.clear();
3970+ if(mSessionResetOnClose)
3971 {
3972- lookupName(participant->mAvatarID);
3973- }
3974- else if(!session->mName.empty())
3975- {
3976- participant->mDisplayName = session->mName;
3977- avatarNameResolved(participant->mAvatarID, session->mName);
3978+ mSessionResetOnClose = false;
3979+ mNonSpatialChannel = false;
3980+ mNextSessionSpatial = true;
3981+ parcelChanged();
3982 }
3983-
3984- // TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here?
3985- LL_INFOS("Voice") << "added caller as participant \"" << participant->mAccountName
3986- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
3987- }
3988- }
3989- }
3990-}
3991-
3992-void LLVoiceClient::sessionRemovedEvent(
3993- std::string &sessionHandle,
3994- std::string &sessionGroupHandle)
3995-{
3996- LL_INFOS("Voice") << "handle " << sessionHandle << LL_ENDL;
3997-
3998- sessionState *session = findSession(sessionHandle);
3999- if(session)
4000- {
4001- leftAudioSession(session);
4002-
4003- // This message invalidates the session's handle. Set it to empty.
4004- setSessionHandle(session);
4005-
4006- // Reset the media state (we now have no info)
4007- session->mMediaStreamState = streamStateUnknown;
4008- session->mTextStreamState = streamStateUnknown;
4009-
4010- // Conditionally delete the session
4011- reapSession(session);
4012- }
4013- else
4014- {
4015- LL_WARNS("Voice") << "unknown session " << sessionHandle << " removed" << LL_ENDL;
4016- }
4017-}
4018-
4019-void LLVoiceClient::reapSession(sessionState *session)
4020-{
4021- if(session)
4022- {
4023- if(!session->mHandle.empty())
4024- {
4025- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL;
4026- }
4027- else if(session->mCreateInProgress)
4028- {
4029- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL;
4030- }
4031- else if(session->mMediaConnectInProgress)
4032- {
4033- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL;
4034- }
4035- else if(session == mAudioSession)
4036- {
4037- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL;
4038- }
4039- else if(session == mNextAudioSession)
4040- {
4041- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL;
4042- }
4043- else
4044- {
4045- // TODO: Question: Should we check for queued text messages here?
4046- // We don't have a reason to keep tracking this session, so just delete it.
4047- LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL;
4048- deleteSession(session);
4049- session = NULL;
4050- }
4051- }
4052- else
4053- {
4054-// LL_DEBUGS("Voice") << "session is NULL" << LL_ENDL;
4055- }
4056-}
4057-
4058-// Returns true if the session seems to indicate we've moved to a region on a different voice server
4059-bool LLVoiceClient::sessionNeedsRelog(sessionState *session)
4060-{
4061- bool result = false;
4062-
4063- if(session != NULL)
4064- {
4065- // Only make this check for spatial channels (so it won't happen for group or p2p calls)
4066- if(session->mIsSpatial)
4067- {
4068- std::string::size_type atsign;
4069
4070- atsign = session->mSIPURI.find("@");
4071-
4072- if(atsign != std::string::npos)
4073- {
4074- std::string urihost = session->mSIPURI.substr(atsign + 1);
4075- if(stricmp(urihost.c_str(), mVoiceSIPURIHostName.c_str()))
4076+ removeAllParticipants();
4077+
4078+ switch(getState())
4079 {
4080- // The hostname in this URI is different from what we expect. This probably means we need to relog.
4081+ case stateJoiningSession:
4082+ case stateSessionJoined:
4083+ case stateRunning:
4084+ case stateLeavingSession:
4085+ case stateJoinSessionFailed:
4086+ case stateJoinSessionFailedWaiting:
4087+ // normal transition
4088+ LL_INFOS("Voice") << "left session " << sessionHandle << "in state " << state2string(getState()) << LL_ENDL;
4089+ setState(stateSessionTerminated);
4090+ break;
4091
4092- // We could make a ProvisionVoiceAccountRequest and compare the result with the current values of
4093- // mVoiceSIPURIHostName and mVoiceAccountServerURI to be really sure, but this is a pretty good indicator.
4094+ case stateSessionTerminated:
4095+ // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
4096+ LL_WARNS("Voice") << "left session " << sessionHandle << "in state " << state2string(getState()) << LL_ENDL;
4097+ break;
4098
4099- result = true;
4100+ default:
4101+ LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
4102+ setState(stateSessionTerminated);
4103+ break;
4104 }
4105+
4106+ // store status values for later notification of observers
4107+ mVivoxErrorStatusCode = statusCode;
4108+ mVivoxErrorStatusString = statusString;
4109+ }
4110+ else
4111+ {
4112+ LL_INFOS("Voice") << "leaving unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << LL_ENDL;
4113 }
4114- }
4115- }
4116-
4117- return result;
4118-}
4119
4120-void LLVoiceClient::leftAudioSession(
4121- sessionState *session)
4122-{
4123- if(mAudioSession == session)
4124- {
4125- switch(getState())
4126- {
4127- case stateJoiningSession:
4128- case stateSessionJoined:
4129- case stateRunning:
4130- case stateLeavingSession:
4131- case stateJoinSessionFailed:
4132- case stateJoinSessionFailedWaiting:
4133- // normal transition
4134- LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
4135- setState(stateSessionTerminated);
4136- break;
4137-
4138- case stateSessionTerminated:
4139- // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
4140- LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
4141- break;
4142-
4143- default:
4144- LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
4145- setState(stateSessionTerminated);
4146- break;
4147- }
4148+ mSessionStateEventHandle.clear();
4149+ mSessionStateEventURI.clear();
4150+ break;
4151+ default:
4152+ LL_WARNS("Voice") << "unknown state: " << state << LL_ENDL;
4153+ break;
4154 }
4155 }
4156
4157-void LLVoiceClient::accountLoginStateChangeEvent(
4158+void LLVoiceClient::loginStateChangeEvent(
4159 std::string &accountHandle,
4160 int statusCode,
4161 std::string &statusString,
4162@@ -4134,571 +2925,110 @@ void LLVoiceClient::accountLoginStateChangeEvent(
4163 }
4164 }
4165
4166-void LLVoiceClient::mediaStreamUpdatedEvent(
4167- std::string &sessionHandle,
4168- std::string &sessionGroupHandle,
4169- int statusCode,
4170- std::string &statusString,
4171- int state,
4172- bool incoming)
4173+void LLVoiceClient::sessionNewEvent(
4174+ std::string &accountHandle,
4175+ std::string &eventSessionHandle,
4176+ int state,
4177+ std::string &nameString,
4178+ std::string &uriString)
4179 {
4180- sessionState *session = findSession(sessionHandle);
4181-
4182- LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL;
4183+ LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
4184
4185- if(session)
4186- {
4187- // We know about this session
4188-
4189- // Save the state for later use
4190- session->mMediaStreamState = state;
4191-
4192- switch(statusCode)
4193- {
4194- case 0:
4195- case 200:
4196- // generic success
4197- // Don't change the saved error code (it may have been set elsewhere)
4198- break;
4199- default:
4200- // save the status code for later
4201- session->mErrorStatusCode = statusCode;
4202- break;
4203- }
4204-
4205- switch(state)
4206- {
4207- case streamStateIdle:
4208- // Standard "left audio session"
4209- session->mVoiceEnabled = false;
4210- session->mMediaConnectInProgress = false;
4211- leftAudioSession(session);
4212- break;
4213-
4214- case streamStateConnected:
4215- session->mVoiceEnabled = true;
4216- session->mMediaConnectInProgress = false;
4217- joinedAudioSession(session);
4218- break;
4219-
4220- case streamStateRinging:
4221- if(incoming)
4222- {
4223- // Send the voice chat invite to the GUI layer
4224- // TODO: Question: Should we correlate with the mute list here?
4225- session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
4226- session->mVoiceInvitePending = true;
4227- if(session->mName.empty())
4228- {
4229- lookupName(session->mCallerID);
4230- }
4231- else
4232- {
4233- // Act like we just finished resolving the name
4234- avatarNameResolved(session->mCallerID, session->mName);
4235- }
4236- }
4237- break;
4238-
4239- default:
4240- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
4241- break;
4242-
4243- }
4244-
4245- }
4246- else
4247+ switch(state)
4248 {
4249- LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL;
4250- }
4251-}
4252+ case 0:
4253+ {
4254+ LL_DEBUGS("Voice") << "session handle = " << eventSessionHandle << ", name = " << nameString << ", uri = " << uriString << LL_ENDL;
4255
4256-void LLVoiceClient::textStreamUpdatedEvent(
4257- std::string &sessionHandle,
4258- std::string &sessionGroupHandle,
4259- bool enabled,
4260- int state,
4261- bool incoming)
4262-{
4263- sessionState *session = findSession(sessionHandle);
4264-
4265- if(session)
4266- {
4267- // Save the state for later use
4268- session->mTextStreamState = state;
4269-
4270- // We know about this session
4271- switch(state)
4272- {
4273- case 0: // We see this when the text stream closes
4274- LL_DEBUGS("Voice") << "stream closed" << LL_ENDL;
4275- break;
4276-
4277- case 1: // We see this on an incoming call from the Connector
4278- // Try to send any text messages queued for this session.
4279- sendQueuedTextMessages(session);
4280-
4281- // Send the text chat invite to the GUI layer
4282- // TODO: Question: Should we correlate with the mute list here?
4283- session->mTextInvitePending = true;
4284- if(session->mName.empty())
4285+ LLUUID caller_id;
4286+ if(IDFromName(nameString, caller_id))
4287 {
4288- lookupName(session->mCallerID);
4289+ gIMMgr->inviteToSession(
4290+ LLIMMgr::computeSessionID(
4291+ IM_SESSION_P2P_INVITE,
4292+ caller_id),
4293+ LLStringUtil::null,
4294+ caller_id,
4295+ LLStringUtil::null,
4296+ IM_SESSION_P2P_INVITE,
4297+ LLIMMgr::INVITATION_TYPE_VOICE,
4298+ eventSessionHandle);
4299 }
4300 else
4301 {
4302- // Act like we just finished resolving the name
4303- avatarNameResolved(session->mCallerID, session->mName);
4304+ LL_WARNS("Voice") << "Could not generate caller id from uri " << uriString << LL_ENDL;
4305 }
4306- break;
4307-
4308- default:
4309- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
4310- break;
4311-
4312- }
4313+ }
4314+ break;
4315+
4316+ default:
4317+ LL_WARNS("Voice") << "unknown state: " << state << LL_ENDL;
4318+ break;
4319 }
4320 }
4321
4322-void LLVoiceClient::participantAddedEvent(
4323- std::string &sessionHandle,
4324- std::string &sessionGroupHandle,
4325+void LLVoiceClient::participantStateChangeEvent(
4326 std::string &uriString,
4327- std::string &alias,
4328+ int statusCode,
4329+ std::string &statusString,
4330+ int state,
4331 std::string &nameString,
4332 std::string &displayNameString,
4333 int participantType)
4334 {
4335- sessionState *session = findSession(sessionHandle);
4336- if(session)
4337- {
4338- participantState *participant = session->addParticipant(uriString);
4339- if(participant)
4340- {
4341- participant->mAccountName = nameString;
4342-
4343- LL_DEBUGS("Voice") << "added participant \"" << participant->mAccountName
4344- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
4345+ participantState *participant = NULL;
4346+ LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
4347
4348- if(participant->mAvatarIDValid)
4349+ switch(state)
4350+ {
4351+ case 7: // I see this when a participant joins
4352+ participant = addParticipant(uriString);
4353+ if(participant)
4354 {
4355- // Initiate a lookup
4356- lookupName(participant->mAvatarID);
4357+ participant->mName = nameString;
4358+ LL_DEBUGS("Voice") << "added participant \"" << participant->mName
4359+ << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
4360 }
4361- else
4362+ break;
4363+ case 9: // I see this when a participant leaves
4364+ participant = findParticipant(uriString);
4365+ if(participant)
4366 {
4367- // If we don't have a valid avatar UUID, we need to fill in the display name to make the active speakers floater work.
4368- std::string namePortion = nameFromsipURI(uriString);
4369- if(namePortion.empty())
4370- {
4371- // Problem with the SIP URI, fall back to the display name
4372- namePortion = displayNameString;
4373- }
4374- if(namePortion.empty())
4375- {
4376- // Problems with both of the above, fall back to the account name
4377- namePortion = nameString;
4378- }
4379-
4380- // Set the display name (which is a hint to the active speakers window not to do its own lookup)
4381- participant->mDisplayName = namePortion;
4382- avatarNameResolved(participant->mAvatarID, namePortion);
4383+ removeParticipant(participant);
4384 }
4385- }
4386- }
4387-}
4388-
4389-void LLVoiceClient::participantRemovedEvent(
4390- std::string &sessionHandle,
4391- std::string &sessionGroupHandle,
4392- std::string &uriString,
4393- std::string &alias,
4394- std::string &nameString)
4395-{
4396- sessionState *session = findSession(sessionHandle);
4397- if(session)
4398- {
4399- participantState *participant = session->findParticipant(uriString);
4400- if(participant)
4401- {
4402- session->removeParticipant(participant);
4403- }
4404- else
4405- {
4406- LL_DEBUGS("Voice") << "unknown participant " << uriString << LL_ENDL;
4407- }
4408- }
4409- else
4410- {
4411- LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
4412+ break;
4413+ default:
4414+ LL_DEBUGS("Voice") << "unknown state: " << state << LL_ENDL;
4415+ break;
4416 }
4417 }
4418
4419-
4420-void LLVoiceClient::participantUpdatedEvent(
4421- std::string &sessionHandle,
4422- std::string &sessionGroupHandle,
4423+void LLVoiceClient::participantPropertiesEvent(
4424 std::string &uriString,
4425- std::string &alias,
4426+ int statusCode,
4427+ std::string &statusString,
4428+ bool isLocallyMuted,
4429 bool isModeratorMuted,
4430 bool isSpeaking,
4431 int volume,
4432 F32 energy)
4433 {
4434- sessionState *session = findSession(sessionHandle);
4435- if(session)
4436- {
4437- participantState *participant = session->findParticipant(uriString);
4438-
4439- if(participant)
4440- {
4441- participant->mIsSpeaking = isSpeaking;
4442- participant->mIsModeratorMuted = isModeratorMuted;
4443-
4444- // SLIM SDK: convert range: ensure that energy is set to zero if is_speaking is false
4445- if (isSpeaking)
4446- {
4447- participant->mSpeakingTimeout.reset();
4448- participant->mPower = energy;
4449- }
4450- else
4451- {
4452- participant->mPower = 0.0f;
4453- }
4454- participant->mVolume = volume;
4455- }
4456- else
4457- {
4458- LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
4459- }
4460- }
4461- else
4462- {
4463- LL_INFOS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
4464- }
4465-}
4466-
4467-void LLVoiceClient::buddyPresenceEvent(
4468- std::string &uriString,
4469- std::string &alias,
4470- std::string &statusString,
4471- std::string &applicationString)
4472-{
4473- buddyListEntry *buddy = findBuddy(uriString);
4474-
4475- if(buddy)
4476+ participantState *participant = findParticipant(uriString);
4477+ if(participant)
4478 {
4479- LL_DEBUGS("Voice") << "Presence event for " << buddy->mDisplayName << " status \"" << statusString << "\", application \"" << applicationString << "\""<< LL_ENDL;
4480- LL_DEBUGS("Voice") << "before: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
4481-
4482- if(applicationString.empty())
4483+ participant->mPTT = !isLocallyMuted;
4484+ participant->mIsSpeaking = isSpeaking;
4485+ participant->mIsModeratorMuted = isModeratorMuted;
4486+ if (isSpeaking)
4487 {
4488- // This presence event is from a client that doesn't set up the Application string. Do things the old-skool way.
4489- // NOTE: this will be needed to support people who aren't on the 3010-class SDK yet.
4490-
4491- if ( stricmp("Unknown", statusString.c_str())== 0)
4492- {
4493- // User went offline with a non-SLim-enabled viewer.
4494- buddy->mOnlineSL = false;
4495- }
4496- else if ( stricmp("Online", statusString.c_str())== 0)
4497- {
4498- // User came online with a non-SLim-enabled viewer.
4499- buddy->mOnlineSL = true;
4500- }
4501- else
4502- {
4503- // If the user is online through SLim, their status will be "Online-slc", "Away", or something else.
4504- // NOTE: we should never see this unless someone is running an OLD version of SLim -- the versions that should be in use now all set the application string.
4505- buddy->mOnlineSLim = true;
4506- }
4507+ participant->mSpeakingTimeout.reset();
4508 }
4509- else if(applicationString.find("SecondLifeViewer") != std::string::npos)
4510- {
4511- // This presence event is from a viewer that sets the application string
4512- if ( stricmp("Unknown", statusString.c_str())== 0)
4513- {
4514- // Viewer says they're offline
4515- buddy->mOnlineSL = false;
4516- }
4517- else
4518- {
4519- // Viewer says they're online
4520- buddy->mOnlineSL = true;
4521- }
4522- }
4523- else
4524- {
4525- // This presence event is from something which is NOT the SL viewer (assume it's SLim).
4526- if ( stricmp("Unknown", statusString.c_str())== 0)
4527- {
4528- // SLim says they're offline
4529- buddy->mOnlineSLim = false;
4530- }
4531- else
4532- {
4533- // SLim says they're online
4534- buddy->mOnlineSLim = true;
4535- }
4536- }
4537-
4538- LL_DEBUGS("Voice") << "after: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
4539-
4540- // HACK -- increment the internal change serial number in the LLRelationship (without changing the actual status), so the UI notices the change.
4541- LLAvatarTracker::instance().setBuddyOnline(buddy->mUUID,LLAvatarTracker::instance().isBuddyOnline(buddy->mUUID));
4542-
4543- notifyFriendObservers();
4544+ participant->mPower = energy;
4545+ participant->mVolume = volume;
4546 }
4547 else
4548 {
4549- LL_DEBUGS("Voice") << "Presence for unknown buddy " << uriString << LL_ENDL;
4550- }
4551-}
4552-
4553-void LLVoiceClient::messageEvent(
4554- std::string &sessionHandle,
4555- std::string &uriString,
4556- std::string &alias,
4557- std::string &messageHeader,
4558- std::string &messageBody,
4559- std::string &applicationString)
4560-{
4561- LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL;
4562-// LL_DEBUGS("Voice") << " header " << messageHeader << ", body: \n" << messageBody << LL_ENDL;
4563-
4564- if(messageHeader.find("text/html") != std::string::npos)
4565- {
4566- std::string rawMessage;
4567-
4568- {
4569- const std::string startMarker = "<body";
4570- const std::string startMarker2 = ">";
4571- const std::string endMarker = "</body>";
4572- const std::string startSpan = "<span";
4573- const std::string endSpan = "</span>";
4574- std::string::size_type start;
4575- std::string::size_type end;
4576-
4577- // Default to displaying the raw string, so the message gets through.
4578- rawMessage = messageBody;
4579-
4580- // Find the actual message text within the XML fragment
4581- start = messageBody.find(startMarker);
4582- start = messageBody.find(startMarker2, start);
4583- end = messageBody.find(endMarker);
4584-
4585- if(start != std::string::npos)
4586- {
4587- start += startMarker2.size();
4588-
4589- if(end != std::string::npos)
4590- end -= start;
4591-
4592- rawMessage.assign(messageBody, start, end);
4593- }
4594- else
4595- {
4596- // Didn't find a <body>, try looking for a <span> instead.
4597- start = messageBody.find(startSpan);
4598- start = messageBody.find(startMarker2, start);
4599- end = messageBody.find(endSpan);
4600-
4601- if(start != std::string::npos)
4602- {
4603- start += startMarker2.size();
4604-
4605- if(end != std::string::npos)
4606- end -= start;
4607-
4608- rawMessage.assign(messageBody, start, end);
4609- }
4610- }
4611- }
4612-
4613-// LL_DEBUGS("Voice") << " raw message = \n" << rawMessage << LL_ENDL;
4614-
4615- // strip formatting tags
4616- {
4617- std::string::size_type start;
4618- std::string::size_type end;
4619-
4620- while((start = rawMessage.find('<')) != std::string::npos)
4621- {
4622- if((end = rawMessage.find('>', start + 1)) != std::string::npos)
4623- {
4624- // Strip out the tag
4625- rawMessage.erase(start, (end + 1) - start);
4626- }
4627- else
4628- {
4629- // Avoid an infinite loop
4630- break;
4631- }
4632- }
4633- }
4634-
4635- // Decode ampersand-escaped chars
4636- {
4637- std::string::size_type mark = 0;
4638-
4639- // The text may contain text encoded with &lt;, &gt;, and &amp;
4640- mark = 0;
4641- while((mark = rawMessage.find("&lt;", mark)) != std::string::npos)
4642- {
4643- rawMessage.replace(mark, 4, "<");
4644- mark += 1;
4645- }
4646-
4647- mark = 0;
4648- while((mark = rawMessage.find("&gt;", mark)) != std::string::npos)
4649- {
4650- rawMessage.replace(mark, 4, ">");
4651- mark += 1;
4652- }
4653-
4654- mark = 0;
4655- while((mark = rawMessage.find("&amp;", mark)) != std::string::npos)
4656- {
4657- rawMessage.replace(mark, 5, "&");
4658- mark += 1;
4659- }
4660- }
4661-
4662- // strip leading/trailing whitespace (since we always seem to get a couple newlines)
4663- LLStringUtil::trim(rawMessage);
4664-
4665-// LL_DEBUGS("Voice") << " stripped message = \n" << rawMessage << LL_ENDL;
4666-
4667- sessionState *session = findSession(sessionHandle);
4668- if(session)
4669- {
4670- bool is_busy = gAgent.getBusy();
4671- bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
4672- bool is_linden = LLMuteList::getInstance()->isLinden(session->mName);
4673- bool quiet_chat = false;
4674- LLChat chat;
4675-
4676- chat.mMuted = is_muted && !is_linden;
4677-
4678- if(!chat.mMuted)
4679- {
4680- chat.mFromID = session->mCallerID;
4681- chat.mFromName = session->mName;
4682- chat.mSourceType = CHAT_SOURCE_AGENT;
4683-
4684- if(is_busy && !is_linden)
4685- {
4686- quiet_chat = true;
4687- // TODO: Question: Return busy mode response here? Or maybe when session is started instead?
4688- }
4689-
4690- std::string fullMessage = std::string(": ") + rawMessage;
4691-
4692- LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
4693- gIMMgr->addMessage(session->mIMSessionID,
4694- session->mCallerID,
4695- session->mName.c_str(),
4696- fullMessage.c_str(),
4697- LLStringUtil::null, // default arg
4698- IM_NOTHING_SPECIAL, // default arg
4699- 0, // default arg
4700- LLUUID::null, // default arg
4701- LLVector3::zero, // default arg
4702- true); // prepend name and make it a link to the user's profile
4703-
4704- chat.mText = std::string("IM: ") + session->mName + std::string(": ") + rawMessage;
4705- // If the chat should come in quietly (i.e. we're in busy mode), pretend it's from a local agent.
4706- LLFloaterChat::addChat( chat, TRUE, quiet_chat );
4707- }
4708- }
4709- }
4710-}
4711-
4712-void LLVoiceClient::sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType)
4713-{
4714- sessionState *session = findSession(sessionHandle);
4715-
4716- if(session)
4717- {
4718- participantState *participant = session->findParticipant(uriString);
4719- if(participant)
4720- {
4721- if (!stricmp(notificationType.c_str(), "Typing"))
4722- {
4723- // Other end started typing
4724- // TODO: The proper way to add a typing notification seems to be LLIMMgr::processIMTypingStart().
4725- // It requires an LLIMInfo for the message, which we don't have here.
4726- }
4727- else if (!stricmp(notificationType.c_str(), "NotTyping"))
4728- {
4729- // Other end stopped typing
4730- // TODO: The proper way to remove a typing notification seems to be LLIMMgr::processIMTypingStop().
4731- // It requires an LLIMInfo for the message, which we don't have here.
4732- }
4733- else
4734- {
4735- LL_DEBUGS("Voice") << "Unknown notification type " << notificationType << "for participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
4736- }
4737- }
4738- else
4739- {
4740- LL_DEBUGS("Voice") << "Unknown participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
4741- }
4742- }
4743- else
4744- {
4745- LL_DEBUGS("Voice") << "Unknown session handle " << sessionHandle << LL_ENDL;
4746- }
4747-}
4748-
4749-void LLVoiceClient::subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType)
4750-{
4751- buddyListEntry *buddy = findBuddy(buddyURI);
4752-
4753- if(!buddy)
4754- {
4755- // Couldn't find buddy by URI, try converting the alias...
4756- if(!alias.empty())
4757- {
4758- LLUUID id;
4759- if(IDFromName(alias, id))
4760- {
4761- buddy = findBuddy(id);
4762- }
4763- }
4764- }
4765-
4766- if(buddy)
4767- {
4768- std::ostringstream stream;
4769-
4770- if(buddy->mCanSeeMeOnline)
4771- {
4772- // Sending the response will create an auto-accept rule
4773- buddy->mHasAutoAcceptListEntry = true;
4774- }
4775- else
4776- {
4777- // Sending the response will create a block rule
4778- buddy->mHasBlockListEntry = true;
4779- }
4780-
4781- if(buddy->mInSLFriends)
4782- {
4783- buddy->mInVivoxBuddies = true;
4784- }
4785-
4786- stream
4787- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.SendSubscriptionReply.1\">"
4788- << "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
4789- << "<BuddyURI>" << buddy->mURI << "</BuddyURI>"
4790- << "<RuleType>" << (buddy->mCanSeeMeOnline?"Allow":"Hide") << "</RuleType>"
4791- << "<AutoAccept>"<< (buddy->mInSLFriends?"1":"0")<< "</AutoAccept>"
4792- << "<SubscriptionHandle>" << subscriptionHandle << "</SubscriptionHandle>"
4793- << "</Request>"
4794- << "\n\n\n";
4795-
4796- writeString(stream.str());
4797+ LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
4798 }
4799 }
4800
4801@@ -4708,226 +3038,155 @@ void LLVoiceClient::auxAudioPropertiesEvent(F32 energy)
4802 mTuningEnergy = energy;
4803 }
4804
4805-void LLVoiceClient::buddyListChanged()
4806-{
4807- // This is called after we receive a BuddyAndGroupListChangedEvent.
4808- mBuddyListMapPopulated = true;
4809- mFriendsListDirty = true;
4810-}
4811-
4812 void LLVoiceClient::muteListChanged()
4813 {
4814 // The user's mute list has been updated. Go through the current participant list and sync it with the mute list.
4815- if(mAudioSession)
4816- {
4817- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
4818-
4819- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
4820- {
4821- participantState *p = iter->second;
4822-
4823- // Check to see if this participant is on the mute list already
4824- if(p->updateMuteState())
4825- mAudioSession->mVolumeDirty = true;
4826- }
4827- }
4828-}
4829
4830-void LLVoiceClient::updateFriends(U32 mask)
4831-{
4832- if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::POWERS))
4833+ participantMap::iterator iter = mParticipantMap.begin();
4834+
4835+ for(; iter != mParticipantMap.end(); iter++)
4836 {
4837- // Just resend the whole friend list to the daemon
4838- mFriendsListDirty = true;
4839+ participantState *p = iter->second;
4840+
4841+ // Check to see if this participant is on the mute list already
4842+ updateMuteState(p);
4843 }
4844 }
4845
4846 /////////////////////////////
4847 // Managing list of participants
4848 LLVoiceClient::participantState::participantState(const std::string &uri) :
4849- mURI(uri),
4850- mPTT(false),
4851- mIsSpeaking(false),
4852- mIsModeratorMuted(false),
4853- mLastSpokeTimestamp(0.f),
4854- mPower(0.f),
4855- mVolume(0),
4856- mOnMuteList(false),
4857- mUserVolume(100),
4858- mVolumeDirty(false),
4859- mAvatarIDValid(false),
4860- mIsSelf(false)
4861+ mURI(uri), mPTT(false), mIsSpeaking(false), mIsModeratorMuted(false), mLastSpokeTimestamp(0.f), mPower(0.f), mVolume(0), mServiceType(serviceTypeUnknown),
4862+ mOnMuteList(false), mUserVolume(100), mVolumeDirty(false), mAvatarIDValid(false)
4863 {
4864 }
4865
4866-LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(const std::string &uri)
4867+LLVoiceClient::participantState *LLVoiceClient::addParticipant(const std::string &uri)
4868 {
4869 participantState *result = NULL;
4870- bool useAlternateURI = false;
4871+
4872+ participantMap::iterator iter = mParticipantMap.find(uri);
4873
4874- // Note: this is mostly the body of LLVoiceClient::sessionState::findParticipant(), but since we need to know if it
4875- // matched the alternate SIP URI (so we can add it properly), we need to reproduce it here.
4876+ if(iter != mParticipantMap.end())
4877 {
4878- participantMap::iterator iter = mParticipantsByURI.find(&uri);
4879-
4880- if(iter == mParticipantsByURI.end())
4881- {
4882- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
4883- {
4884- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
4885- // Use mSIPURI instead, since it will be properly encoded.
4886- iter = mParticipantsByURI.find(&(mSIPURI));
4887- useAlternateURI = true;
4888- }
4889- }
4890-
4891- if(iter != mParticipantsByURI.end())
4892- {
4893- result = iter->second;
4894- }
4895+ // Found a matching participant already in the map.
4896+ result = iter->second;
4897 }
4898-
4899+
4900 if(!result)
4901 {
4902 // participant isn't already in one list or the other.
4903- result = new participantState(useAlternateURI?mSIPURI:uri);
4904- mParticipantsByURI.insert(participantMap::value_type(&(result->mURI), result));
4905- mParticipantsChanged = true;
4906+ result = new participantState(uri);
4907+ mParticipantMap.insert(participantMap::value_type(uri, result));
4908+ mParticipantMapChanged = true;
4909
4910 // Try to do a reverse transform on the URI to get the GUID back.
4911 {
4912 LLUUID id;
4913- if(IDFromName(result->mURI, id))
4914+ if(IDFromName(uri, id))
4915 {
4916 result->mAvatarIDValid = true;
4917 result->mAvatarID = id;
4918
4919- if(result->updateMuteState())
4920- mVolumeDirty = true;
4921- }
4922- else
4923- {
4924- // Create a UUID by hashing the URI, but do NOT set mAvatarIDValid.
4925- // This tells both code in LLVoiceClient and code in llfloateractivespeakers.cpp that the ID will not be in the name cache.
4926- setUUIDFromStringHash(result->mAvatarID, uri);
4927+ updateMuteState(result);
4928 }
4929 }
4930
4931- mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result));
4932-
4933 LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
4934 }
4935
4936 return result;
4937 }
4938
4939-bool LLVoiceClient::participantState::updateMuteState()
4940+void LLVoiceClient::updateMuteState(participantState *p)
4941 {
4942- bool result = false;
4943-
4944- if(mAvatarIDValid)
4945+ if(p->mAvatarIDValid)
4946 {
4947- bool isMuted = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
4948- if(mOnMuteList != isMuted)
4949+ bool isMuted = LLMuteList::getInstance()->isMuted(p->mAvatarID, LLMute::flagVoiceChat);
4950+ if(p->mOnMuteList != isMuted)
4951 {
4952- mOnMuteList = isMuted;
4953+ p->mOnMuteList = isMuted;
4954+ p->mVolumeDirty = true;
4955 mVolumeDirty = true;
4956- result = true;
4957 }
4958 }
4959- return result;
4960 }
4961
4962-void LLVoiceClient::sessionState::removeParticipant(LLVoiceClient::participantState *participant)
4963+void LLVoiceClient::removeParticipant(LLVoiceClient::participantState *participant)
4964 {
4965 if(participant)
4966 {
4967- participantMap::iterator iter = mParticipantsByURI.find(&(participant->mURI));
4968- participantUUIDMap::iterator iter2 = mParticipantsByUUID.find(&(participant->mAvatarID));
4969-
4970+ participantMap::iterator iter = mParticipantMap.find(participant->mURI);
4971+
4972 LL_DEBUGS("Voice") << "participant \"" << participant->mURI << "\" (" << participant->mAvatarID << ") removed." << LL_ENDL;
4973-
4974- if(iter == mParticipantsByURI.end())
4975- {
4976- LL_ERRS("Voice") << "Internal error: participant " << participant->mURI << " not in URI map" << LL_ENDL;
4977- }
4978- else if(iter2 == mParticipantsByUUID.end())
4979- {
4980- LL_ERRS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL;
4981- }
4982- else if(iter->second != iter2->second)
4983- {
4984- LL_ERRS("Voice") << "Internal error: participant mismatch!" << LL_ENDL;
4985- }
4986- else
4987- {
4988- mParticipantsByURI.erase(iter);
4989- mParticipantsByUUID.erase(iter2);
4990-
4991- delete participant;
4992- mParticipantsChanged = true;
4993- }
4994+
4995+ mParticipantMap.erase(iter);
4996+ delete participant;
4997+ mParticipantMapChanged = true;
4998 }
4999 }
5000
5001-void LLVoiceClient::sessionState::removeAllParticipants()
5002+void LLVoiceClient::removeAllParticipants()
5003 {
5004 LL_DEBUGS("Voice") << "called" << LL_ENDL;
5005
5006- while(!mParticipantsByURI.empty())
5007+ while(!mParticipantMap.empty())
5008 {
5009- removeParticipant(mParticipantsByURI.begin()->second);
5010- }
5011-
5012- if(!mParticipantsByUUID.empty())
5013- {
5014- LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL
5015+ removeParticipant(mParticipantMap.begin()->second);
5016 }
5017 }
5018
5019 LLVoiceClient::participantMap *LLVoiceClient::getParticipantList(void)
5020 {
5021- participantMap *result = NULL;
5022- if(mAudioSession)
5023- {
5024- result = &(mAudioSession->mParticipantsByURI);
5025- }
5026- return result;
5027+ return &mParticipantMap;
5028 }
5029
5030
5031-LLVoiceClient::participantState *LLVoiceClient::sessionState::findParticipant(const std::string &uri)
5032+LLVoiceClient::participantState *LLVoiceClient::findParticipant(const std::string &uri)
5033 {
5034 participantState *result = NULL;
5035
5036- participantMap::iterator iter = mParticipantsByURI.find(&uri);
5037-
5038- if(iter == mParticipantsByURI.end())
5039+ // Don't find any participants if we're not connected. This is so that we don't continue to get stale data
5040+ // after the daemon dies.
5041+ if(mConnected)
5042 {
5043- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
5044+ participantMap::iterator iter = mParticipantMap.find(uri);
5045+
5046+ if(iter != mParticipantMap.end())
5047 {
5048- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
5049- // Look up the other URI
5050- iter = mParticipantsByURI.find(&(mSIPURI));
5051+ result = iter->second;
5052 }
5053 }
5054-
5055- if(iter != mParticipantsByURI.end())
5056- {
5057- result = iter->second;
5058- }
5059-
5060+
5061 return result;
5062 }
5063
5064-LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByID(const LLUUID& id)
5065+
5066+LLVoiceClient::participantState *LLVoiceClient::findParticipantByAvatar(LLVOAvatar *avatar)
5067 {
5068 participantState * result = NULL;
5069- participantUUIDMap::iterator iter = mParticipantsByUUID.find(&id);
5070
5071- if(iter != mParticipantsByUUID.end())
5072+ // You'd think this would work, but it doesn't...
5073+// std::string uri = sipURIFromAvatar(avatar);
5074+
5075+ // Currently, the URI is just the account name.
5076+ std::string loginName = nameFromAvatar(avatar);
5077+ result = findParticipant(loginName);
5078+
5079+ if(result != NULL)
5080 {
5081- result = iter->second;
5082+ if(!result->mAvatarIDValid)
5083+ {
5084+ result->mAvatarID = avatar->getID();
5085+ result->mAvatarIDValid = true;
5086+
5087+ // We just figured out the avatar ID, so the participant list has "changed" from the perspective of anyone who uses that to identify participants.
5088+ mParticipantMapChanged = true;
5089+
5090+ updateMuteState(result);
5091+ }
5092+
5093+
5094 }
5095
5096 return result;
5097@@ -4936,19 +3195,43 @@ LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByI
5098 LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID& id)
5099 {
5100 participantState * result = NULL;
5101+
5102+ // Currently, the URI is just the account name.
5103+ std::string loginName = nameFromID(id);
5104+ result = findParticipant(loginName);
5105+
5106+ return result;
5107+}
5108+
5109+
5110+void LLVoiceClient::clearChannelMap(void)
5111+{
5112+ mChannelMap.clear();
5113+}
5114+
5115+void LLVoiceClient::addChannelMapEntry(std::string &name, std::string &uri)
5116+{
5117+ LL_DEBUGS("Voice") << "Adding channel name mapping: " << name << " -> " << uri << LL_ENDL;
5118+ mChannelMap.insert(channelMap::value_type(name, uri));
5119+}
5120+
5121+std::string LLVoiceClient::findChannelURI(std::string &name)
5122+{
5123+ std::string result;
5124
5125- if(mAudioSession)
5126+ channelMap::iterator iter = mChannelMap.find(name);
5127+
5128+ if(iter != mChannelMap.end())
5129 {
5130- result = mAudioSession->findParticipantByID(id);
5131+ result = iter->second;
5132 }
5133
5134 return result;
5135 }
5136
5137-
5138 void LLVoiceClient::parcelChanged()
5139 {
5140- if(getState() >= stateNoChannel)
5141+ if(getState() >= stateLoggedIn)
5142 {
5143 // If the user is logged in, start a channel lookup.
5144 LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
5145@@ -4962,7 +3245,7 @@ void LLVoiceClient::parcelChanged()
5146 }
5147 else
5148 {
5149- // The transition to stateNoChannel needs to kick this off again.
5150+ // The transition to stateLoggedIn needs to kick this off again.
5151 LL_INFOS("Voice") << "not logged in yet, deferring" << LL_ENDL;
5152 }
5153 }
5154@@ -4970,17 +3253,12 @@ void LLVoiceClient::parcelChanged()
5155 void LLVoiceClient::switchChannel(
5156 std::string uri,
5157 bool spatial,
5158- bool no_reconnect,
5159- bool is_p2p,
5160+ bool noReconnect,
5161 std::string hash)
5162 {
5163 bool needsSwitch = false;
5164
5165- LL_DEBUGS("Voice")
5166- << "called in state " << state2string(getState())
5167- << " with uri \"" << uri << "\""
5168- << (spatial?", spatial is true":", spatial is false")
5169- << LL_ENDL;
5170+ LL_DEBUGS("Voice") << "called in state " << state2string(getState()) << " with uri \"" << uri << "\"" << LL_ENDL;
5171
5172 switch(getState())
5173 {
5174@@ -4990,18 +3268,18 @@ void LLVoiceClient::switchChannel(
5175 // Always switch to the new URI from these states.
5176 needsSwitch = true;
5177 break;
5178-
5179+
5180 default:
5181 if(mSessionTerminateRequested)
5182 {
5183 // If a terminate has been requested, we need to compare against where the URI we're already headed to.
5184- if(mNextAudioSession && (mNextAudioSession->mSIPURI != uri))
5185+ if(mNextSessionURI != uri)
5186 needsSwitch = true;
5187 }
5188 else
5189 {
5190 // Otherwise, compare against the URI we're in now.
5191- if(mAudioSession && (mAudioSession->mSIPURI != uri))
5192+ if(mSessionURI != uri)
5193 needsSwitch = true;
5194 }
5195 break;
5196@@ -5009,28 +3287,22 @@ void LLVoiceClient::switchChannel(
5197
5198 if(needsSwitch)
5199 {
5200+ mNextSessionURI = uri;
5201+ mNextSessionHash = hash;
5202+ mNextSessionHandle.clear();
5203+ mNextP2PSessionURI.clear();
5204+ mNextSessionSpatial = spatial;
5205+ mNextSessionNoReconnect = noReconnect;
5206+
5207 if(uri.empty())
5208 {
5209 // Leave any channel we may be in
5210 LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL;
5211-
5212- sessionState *oldSession = mNextAudioSession;
5213- mNextAudioSession = NULL;
5214-
5215- // The old session may now need to be deleted.
5216- reapSession(oldSession);
5217-
5218 notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
5219 }
5220 else
5221 {
5222 LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL;
5223-
5224- mNextAudioSession = addSession(uri);
5225- mNextAudioSession->mHash = hash;
5226- mNextAudioSession->mIsSpatial = spatial;
5227- mNextAudioSession->mReconnect = !no_reconnect;
5228- mNextAudioSession->mIsP2P = is_p2p;
5229 }
5230
5231 if(getState() <= stateNoChannel)
5232@@ -5045,10 +3317,15 @@ void LLVoiceClient::switchChannel(
5233 }
5234 }
5235
5236-void LLVoiceClient::joinSession(sessionState *session)
5237+void LLVoiceClient::joinSession(std::string handle, std::string uri)
5238 {
5239- mNextAudioSession = session;
5240-
5241+ mNextSessionURI.clear();
5242+ mNextSessionHash.clear();
5243+ mNextP2PSessionURI = uri;
5244+ mNextSessionHandle = handle;
5245+ mNextSessionSpatial = false;
5246+ mNextSessionNoReconnect = false;
5247+
5248 if(getState() <= stateNoChannel)
5249 {
5250 // We're already set up to join a channel, just needed to fill in the session handle
5251@@ -5064,7 +3341,7 @@ void LLVoiceClient::setNonSpatialChannel(
5252 const std::string &uri,
5253 const std::string &credentials)
5254 {
5255- switchChannel(uri, false, false, false, credentials);
5256+ switchChannel(uri, false, false, credentials);
5257 }
5258
5259 void LLVoiceClient::setSpatialChannel(
5260@@ -5072,216 +3349,51 @@ void LLVoiceClient::setSpatialChannel(
5261 const std::string &credentials)
5262 {
5263 mSpatialSessionURI = uri;
5264- mSpatialSessionCredentials = credentials;
5265 mAreaVoiceDisabled = mSpatialSessionURI.empty();
5266
5267 LL_DEBUGS("Voice") << "got spatial channel uri: \"" << uri << "\"" << LL_ENDL;
5268
5269- if((mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial)))
5270+ if(mNonSpatialChannel || !mNextSessionSpatial)
5271 {
5272 // User is in a non-spatial chat or joining a non-spatial chat. Don't switch channels.
5273 LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL;
5274 }
5275 else
5276 {
5277- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
5278+ switchChannel(mSpatialSessionURI, true, false, credentials);
5279 }
5280 }
5281
5282-void LLVoiceClient::callUser(const LLUUID &uuid)
5283+void LLVoiceClient::callUser(LLUUID &uuid)
5284 {
5285 std::string userURI = sipURIFromID(uuid);
5286
5287- switchChannel(userURI, false, true, true);
5288-}
5289-
5290-LLVoiceClient::sessionState* LLVoiceClient::startUserIMSession(const LLUUID &uuid)
5291-{
5292- // Figure out if a session with the user already exists
5293- sessionState *session = findSession(uuid);
5294- if(!session)
5295- {
5296- // No session with user, need to start one.
5297- std::string uri = sipURIFromID(uuid);
5298- session = addSession(uri);
5299- session->mIsSpatial = false;
5300- session->mReconnect = false;
5301- session->mIsP2P = true;
5302- session->mCallerID = uuid;
5303- }
5304-
5305- if(session)
5306- {
5307- if(session->mHandle.empty())
5308- {
5309- // Session isn't active -- start it up.
5310- sessionCreateSendMessage(session, false, true);
5311- }
5312- else
5313- {
5314- // Session is already active -- start up text.
5315- sessionTextConnectSendMessage(session);
5316- }
5317- }
5318-
5319- return session;
5320-}
5321-
5322-bool LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message)
5323-{
5324- bool result = false;
5325-
5326- // Attempt to locate the indicated session
5327- sessionState *session = startUserIMSession(participant_id);
5328- if(session)
5329- {
5330- // found the session, attempt to send the message
5331- session->mTextMsgQueue.push(message);
5332-
5333- // Try to send queued messages (will do nothing if the session is not open yet)
5334- sendQueuedTextMessages(session);
5335-
5336- // The message is queued, so we succeed.
5337- result = true;
5338- }
5339- else
5340- {
5341- LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL;
5342- }
5343-
5344- return result;
5345-}
5346-
5347-void LLVoiceClient::sendQueuedTextMessages(sessionState *session)
5348-{
5349- if(session->mTextStreamState == 1)
5350- {
5351- if(!session->mTextMsgQueue.empty())
5352- {
5353- std::ostringstream stream;
5354-
5355- while(!session->mTextMsgQueue.empty())
5356- {
5357- std::string message = session->mTextMsgQueue.front();
5358- session->mTextMsgQueue.pop();
5359- stream
5360- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SendMessage.1\">"
5361- << "<SessionHandle>" << session->mHandle << "</SessionHandle>"
5362- << "<MessageHeader>text/HTML</MessageHeader>"
5363- << "<MessageBody>" << message << "</MessageBody>"
5364- << "</Request>"
5365- << "\n\n\n";
5366- }
5367- writeString(stream.str());
5368- }
5369- }
5370- else
5371- {
5372- // Session isn't connected yet, defer until later.
5373- }
5374-}
5375-
5376-void LLVoiceClient::endUserIMSession(const LLUUID &uuid)
5377-{
5378- // Figure out if a session with the user exists
5379- sessionState *session = findSession(uuid);
5380- if(session)
5381- {
5382- // found the session
5383- if(!session->mHandle.empty())
5384- {
5385- sessionTextDisconnectSendMessage(session);
5386- }
5387- }
5388- else
5389- {
5390- LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL;
5391- }
5392+ switchChannel(userURI, false, true);
5393 }
5394
5395-bool LLVoiceClient::answerInvite(std::string &sessionHandle)
5396+void LLVoiceClient::answerInvite(std::string &sessionHandle, LLUUID& other_user_id)
5397 {
5398- // this is only ever used to answer incoming p2p call invites.
5399-
5400- sessionState *session = findSession(sessionHandle);
5401- if(session)
5402- {
5403- session->mIsSpatial = false;
5404- session->mReconnect = false;
5405- session->mIsP2P = true;
5406-
5407- joinSession(session);
5408- return true;
5409- }
5410-
5411- return false;
5412-}
5413-
5414-bool LLVoiceClient::isOnlineSIP(const LLUUID &id)
5415-{
5416- bool result = false;
5417- buddyListEntry *buddy = findBuddy(id);
5418- if(buddy)
5419- {
5420- result = buddy->mOnlineSLim;
5421- LL_DEBUGS("Voice") << "Buddy " << buddy->mDisplayName << " is SIP " << (result?"online":"offline") << LL_ENDL;
5422- }
5423-
5424- if(!result)
5425- {
5426- // This user isn't on the buddy list or doesn't show online status through the buddy list, but could be a participant in an existing session if they initiated a text IM.
5427- sessionState *session = findSession(id);
5428- if(session && !session->mHandle.empty())
5429- {
5430- if((session->mTextStreamState != streamStateUnknown) || (session->mMediaStreamState > streamStateIdle))
5431- {
5432- LL_DEBUGS("Voice") << "Open session with " << id << " found, returning SIP online state" << LL_ENDL;
5433- // we have a p2p text session open with this user, so by definition they're online.
5434- result = true;
5435- }
5436- }
5437- }
5438-
5439- return result;
5440+ joinSession(sessionHandle, sipURIFromID(other_user_id));
5441 }
5442
5443 void LLVoiceClient::declineInvite(std::string &sessionHandle)
5444 {
5445- sessionState *session = findSession(sessionHandle);
5446- if(session)
5447- {
5448- sessionMediaDisconnectSendMessage(session);
5449- }
5450+ sessionTerminateByHandle(sessionHandle);
5451 }
5452
5453 void LLVoiceClient::leaveNonSpatialChannel()
5454 {
5455- LL_DEBUGS("Voice")
5456- << "called in state " << state2string(getState())
5457- << LL_ENDL;
5458-
5459- // Make sure we don't rejoin the current session.
5460- sessionState *oldNextSession = mNextAudioSession;
5461- mNextAudioSession = NULL;
5462-
5463- // Most likely this will still be the current session at this point, but check it anyway.
5464- reapSession(oldNextSession);
5465-
5466- verifySessionState();
5467-
5468- sessionTerminate();
5469+ switchChannel(mSpatialSessionURI);
5470 }
5471
5472 std::string LLVoiceClient::getCurrentChannel()
5473 {
5474- std::string result;
5475-
5476 if((getState() == stateRunning) && !mSessionTerminateRequested)
5477 {
5478- result = getAudioSessionURI();
5479+ return mSessionURI;
5480 }
5481
5482- return result;
5483+ return "";
5484 }
5485
5486 bool LLVoiceClient::inProximalChannel()
5487@@ -5290,7 +3402,7 @@ bool LLVoiceClient::inProximalChannel()
5488
5489 if((getState() == stateRunning) && !mSessionTerminateRequested)
5490 {
5491- result = inSpatialChannel();
5492+ result = !mNonSpatialChannel;
5493 }
5494
5495 return result;
5496@@ -5302,7 +3414,7 @@ std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
5497 result = "sip:";
5498 result += nameFromID(id);
5499 result += "@";
5500- result += mVoiceSIPURIHostName;
5501+ result += mAccountServerName;
5502
5503 return result;
5504 }
5505@@ -5315,7 +3427,7 @@ std::string LLVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar)
5506 result = "sip:";
5507 result += nameFromID(avatar->getID());
5508 result += "@";
5509- result += mVoiceSIPURIHostName;
5510+ result += mAccountServerName;
5511 }
5512
5513 return result;
5514@@ -5334,13 +3446,6 @@ std::string LLVoiceClient::nameFromAvatar(LLVOAvatar *avatar)
5515 std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
5516 {
5517 std::string result;
5518-
5519- if (uuid.isNull()) {
5520- //VIVOX, the uuid emtpy look for the mURIString and return that instead.
5521- //result.assign(uuid.mURIStringName);
5522- LLStringUtil::replaceChar(result, '_', ' ');
5523- return result;
5524- }
5525 // Prepending this apparently prevents conflicts with reserved names inside the vivox and diamondware code.
5526 result = "x";
5527
5528@@ -5354,24 +3459,13 @@ std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
5529 // If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
5530 // echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
5531
5532- // The reverse transform can be done with:
5533- // echo 'x5mkTKmxDTuGnjWyC__WfMg==' |cut -b 2- -|tr '_-' '/+' |openssl base64 -d|xxd -p
5534-
5535 return result;
5536 }
5537
5538-bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
5539+bool LLVoiceClient::IDFromName(const std::string name, LLUUID &uuid)
5540 {
5541 bool result = false;
5542
5543- // SLIM SDK: The "name" may actually be a SIP URI such as: "sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com"
5544- // If it is, convert to a bare name before doing the transform.
5545- std::string name = nameFromsipURI(inName);
5546-
5547- // Doesn't look like a SIP URI, assume it's an actual name.
5548- if(name.empty())
5549- name = inName;
5550-
5551 // This will only work if the name is of the proper form.
5552 // As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is:
5553 // "xFnPP04IpREWNkuw1cOXlhw=="
5554@@ -5393,13 +3487,6 @@ bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
5555 memcpy(uuid.mData, rawuuid, UUID_BYTES);
5556 result = true;
5557 }
5558- }
5559-
5560- if(!result)
5561- {
5562- // VIVOX: not a standard account name, just copy the URI name mURIString field
5563- // and hope for the best. bpj
5564- uuid.setNull(); // VIVOX, set the uuid field to nulls
5565 }
5566
5567 return result;
5568@@ -5416,59 +3503,13 @@ std::string LLVoiceClient::sipURIFromName(std::string &name)
5569 result = "sip:";
5570 result += name;
5571 result += "@";
5572- result += mVoiceSIPURIHostName;
5573+ result += mAccountServerName;
5574
5575 // LLStringUtil::toLower(result);
5576
5577 return result;
5578 }
5579
5580-std::string LLVoiceClient::nameFromsipURI(const std::string &uri)
5581-{
5582- std::string result;
5583-
5584- std::string::size_type sipOffset, atOffset;
5585- sipOffset = uri.find("sip:");
5586- atOffset = uri.find("@");
5587- if((sipOffset != std::string::npos) && (atOffset != std::string::npos))
5588- {
5589- result = uri.substr(sipOffset + 4, atOffset - (sipOffset + 4));
5590- }
5591-
5592- return result;
5593-}
5594-
5595-bool LLVoiceClient::inSpatialChannel(void)
5596-{
5597- bool result = false;
5598-
5599- if(mAudioSession)
5600- result = mAudioSession->mIsSpatial;
5601-
5602- return result;
5603-}
5604-
5605-std::string LLVoiceClient::getAudioSessionURI()
5606-{
5607- std::string result;
5608-
5609- if(mAudioSession)
5610- result = mAudioSession->mSIPURI;
5611-
5612- return result;
5613-}
5614-
5615-std::string LLVoiceClient::getAudioSessionHandle()
5616-{
5617- std::string result;
5618-
5619- if(mAudioSession)
5620- result = mAudioSession->mHandle;
5621-
5622- return result;
5623-}
5624-
5625-
5626 /////////////////////////////
5627 // Sending updates of current state
5628
5629@@ -5507,8 +3548,7 @@ void LLVoiceClient::updatePosition(void)
5630 LLMatrix3 rot;
5631 LLVector3d pos;
5632
5633- // TODO: If camera and avatar velocity are actually used by the voice system, we could compute them here...
5634- // They're currently always set to zero.
5635+ // MBW -- XXX -- Setting both camera and avatar velocity to 0 for now. May figure it out later...
5636
5637 // Send the current camera position to the voice code
5638 rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (), LLViewerCamera::getInstance()->getUpAxis());
5639@@ -5523,7 +3563,7 @@ void LLVoiceClient::updatePosition(void)
5640 rot = agent->getRootJoint()->getWorldRotation().getMatrix3();
5641
5642 pos = agent->getPositionGlobal();
5643- // TODO: Can we get the head offset from outside the LLVOAvatar?
5644+ // MBW -- XXX -- Can we get the head offset from outside the LLVOAvatar?
5645 // pos += LLVector3d(mHeadOffset);
5646 pos += LLVector3d(0.f, 0.f, 1.f);
5647
5648@@ -5629,8 +3669,8 @@ void LLVoiceClient::setVoiceEnabled(bool enabled)
5649 }
5650 else
5651 {
5652- // Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
5653- LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
5654+ // for now, leave active channel, to auto join when turning voice back on
5655+ //LLVoiceChannel::getCurrentVoiceChannel->deactivate();
5656 }
5657 }
5658 }
5659@@ -5710,34 +3750,56 @@ void LLVoiceClient::setEarLocation(S32 loc)
5660
5661 void LLVoiceClient::setVoiceVolume(F32 volume)
5662 {
5663- int scaled_volume = scale_speaker_volume(volume);
5664+ LL_DEBUGS("Voice") << "volume is " << volume << LL_ENDL;
5665
5666- if(scaled_volume != mSpeakerVolume)
5667+ // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
5668+ // Map it as follows: 0.0 -> -100, 0.5 -> 24, 1.0 -> 50
5669+
5670+ volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
5671+ int scaledVolume = 24; // offset scaledVolume by its default level
5672+ if(volume < 0.0f)
5673+ scaledVolume += ((int)(volume * 248.0f)); // (24 - (-100)) * 2
5674+ else
5675+ scaledVolume += ((int)(volume * 52.0f)); // (50 - 24) * 2
5676+
5677+ if(scaledVolume != mSpeakerVolume)
5678 {
5679- if((scaled_volume == 0) || (mSpeakerVolume == 0))
5680+ if((scaledVolume == -100) || (mSpeakerVolume == -100))
5681 {
5682 mSpeakerMuteDirty = true;
5683 }
5684
5685- mSpeakerVolume = scaled_volume;
5686+ mSpeakerVolume = scaledVolume;
5687 mSpeakerVolumeDirty = true;
5688 }
5689 }
5690
5691 void LLVoiceClient::setMicGain(F32 volume)
5692 {
5693- int scaled_volume = scale_mic_volume(volume);
5694-
5695- if(scaled_volume != mMicVolume)
5696+ int scaledVolume = ((int)(volume * 100.0f)) - 100;
5697+ if(scaledVolume != mMicVolume)
5698 {
5699- mMicVolume = scaled_volume;
5700+ mMicVolume = scaledVolume;
5701 mMicVolumeDirty = true;
5702 }
5703 }
5704
5705+void LLVoiceClient::setVivoxDebugServerName(std::string &serverName)
5706+{
5707+ if(!mAccountServerName.empty())
5708+ {
5709+ // The name has been filled in already, which means we know whether we're connecting to agni or not.
5710+ if(!sConnectingToAgni)
5711+ {
5712+ // Only use the setting if we're connecting to a development grid -- always use bhr when on agni.
5713+ mAccountServerName = serverName;
5714+ }
5715+ }
5716+}
5717+
5718 void LLVoiceClient::keyDown(KEY key, MASK mask)
5719 {
5720-// LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
5721+ LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
5722
5723 if (gKeyboard->getKeyRepeated(key))
5724 {
5725@@ -5875,6 +3937,19 @@ BOOL LLVoiceClient::getUsingPTT(const LLUUID& id)
5726 return result;
5727 }
5728
5729+BOOL LLVoiceClient::getPTTPressed(const LLUUID& id)
5730+{
5731+ BOOL result = FALSE;
5732+
5733+ participantState *participant = findParticipantByID(id);
5734+ if(participant)
5735+ {
5736+ result = participant->mPTT;
5737+ }
5738+
5739+ return result;
5740+}
5741+
5742 BOOL LLVoiceClient::getOnMuteList(const LLUUID& id)
5743 {
5744 BOOL result = FALSE;
5745@@ -5906,841 +3981,144 @@ F32 LLVoiceClient::getUserVolume(const LLUUID& id)
5746
5747 void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
5748 {
5749- if(mAudioSession)
5750- {
5751- participantState *participant = findParticipantByID(id);
5752- if (participant)
5753- {
5754- // volume can amplify by as much as 4x!
5755- S32 ivol = (S32)(400.f * volume * volume);
5756- participant->mUserVolume = llclamp(ivol, 0, 400);
5757- participant->mVolumeDirty = TRUE;
5758- mAudioSession->mVolumeDirty = TRUE;
5759- }
5760- }
5761-}
5762-
5763-std::string LLVoiceClient::getGroupID(const LLUUID& id)
5764-{
5765- std::string result;
5766-
5767 participantState *participant = findParticipantByID(id);
5768- if(participant)
5769+ if (participant)
5770 {
5771- result = participant->mGroupID;
5772+ // volume can amplify by as much as 4x!
5773+ S32 ivol = (S32)(400.f * volume * volume);
5774+ participant->mUserVolume = llclamp(ivol, 0, 400);
5775+ participant->mVolumeDirty = TRUE;
5776+ mVolumeDirty = TRUE;
5777 }
5778-
5779- return result;
5780 }
5781
5782-BOOL LLVoiceClient::getAreaVoiceDisabled()
5783-{
5784- return mAreaVoiceDisabled;
5785-}
5786-
5787-void LLVoiceClient::recordingLoopStart(int seconds, int deltaFramesPerControlFrame)
5788-{
5789-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Start)" << LL_ENDL;
5790-
5791- if(!mMainSessionGroupHandle.empty())
5792- {
5793- std::ostringstream stream;
5794- stream
5795- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
5796- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
5797- << "<RecordingControlType>Start</RecordingControlType>"
5798- << "<DeltaFramesPerControlFrame>" << deltaFramesPerControlFrame << "</DeltaFramesPerControlFrame>"
5799- << "<Filename>" << "" << "</Filename>"
5800- << "<EnableAudioRecordingEvents>false</EnableAudioRecordingEvents>"
5801- << "<LoopModeDurationSeconds>" << seconds << "</LoopModeDurationSeconds>"
5802- << "</Request>\n\n\n";
5803
5804
5805- writeString(stream.str());
5806- }
5807-}
5808-
5809-void LLVoiceClient::recordingLoopSave(const std::string& filename)
5810+LLVoiceClient::serviceType LLVoiceClient::getServiceType(const LLUUID& id)
5811 {
5812-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Flush)" << LL_ENDL;
5813+ serviceType result = serviceTypeUnknown;
5814
5815- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
5816- {
5817- std::ostringstream stream;
5818- stream
5819- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
5820- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
5821- << "<RecordingControlType>Flush</RecordingControlType>"
5822- << "<Filename>" << filename << "</Filename>"
5823- << "</Request>\n\n\n";
5824-
5825- writeString(stream.str());
5826- }
5827-}
5828-
5829-void LLVoiceClient::recordingStop()
5830-{
5831-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Stop)" << LL_ENDL;
5832-
5833- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
5834- {
5835- std::ostringstream stream;
5836- stream
5837- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlRecording.1\">"
5838- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
5839- << "<RecordingControlType>Stop</RecordingControlType>"
5840- << "</Request>\n\n\n";
5841-
5842- writeString(stream.str());
5843- }
5844-}
5845-
5846-void LLVoiceClient::filePlaybackStart(const std::string& filename)
5847-{
5848-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Start)" << LL_ENDL;
5849-
5850- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
5851- {
5852- std::ostringstream stream;
5853- stream
5854- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
5855- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
5856- << "<RecordingControlType>Start</RecordingControlType>"
5857- << "<Filename>" << filename << "</Filename>"
5858- << "</Request>\n\n\n";
5859-
5860- writeString(stream.str());
5861- }
5862-}
5863-
5864-void LLVoiceClient::filePlaybackStop()
5865-{
5866-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Stop)" << LL_ENDL;
5867-
5868- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
5869- {
5870- std::ostringstream stream;
5871- stream
5872- << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"SessionGroup.ControlPlayback.1\">"
5873- << "<SessionGroupHandle>" << mMainSessionGroupHandle << "</SessionGroupHandle>"
5874- << "<RecordingControlType>Stop</RecordingControlType>"
5875- << "</Request>\n\n\n";
5876-
5877- writeString(stream.str());
5878- }
5879-}
5880-
5881-void LLVoiceClient::filePlaybackSetPaused(bool paused)
5882-{
5883- // TODO: Implement once Vivox gives me a sample
5884-}
5885-
5886-void LLVoiceClient::filePlaybackSetMode(bool vox, float speed)
5887-{
5888- // TODO: Implement once Vivox gives me a sample
5889-}
5890-
5891-LLVoiceClient::sessionState::sessionState() :
5892- mMediaStreamState(streamStateUnknown),
5893- mTextStreamState(streamStateUnknown),
5894- mCreateInProgress(false),
5895- mMediaConnectInProgress(false),
5896- mVoiceInvitePending(false),
5897- mTextInvitePending(false),
5898- mSynthesizedCallerID(false),
5899- mIsChannel(false),
5900- mIsSpatial(false),
5901- mIsP2P(false),
5902- mIncoming(false),
5903- mVoiceEnabled(false),
5904- mReconnect(false),
5905- mVolumeDirty(false),
5906- mParticipantsChanged(false)
5907-{
5908-}
5909-
5910-LLVoiceClient::sessionState::~sessionState()
5911-{
5912- removeAllParticipants();
5913-}
5914-
5915-LLVoiceClient::sessionIterator LLVoiceClient::sessionsBegin(void)
5916-{
5917- return mSessions.begin();
5918-}
5919-
5920-LLVoiceClient::sessionIterator LLVoiceClient::sessionsEnd(void)
5921-{
5922- return mSessions.end();
5923-}
5924-
5925-
5926-LLVoiceClient::sessionState *LLVoiceClient::findSession(const std::string &handle)
5927-{
5928- sessionState *result = NULL;
5929- sessionMap::iterator iter = mSessionsByHandle.find(&handle);
5930- if(iter != mSessionsByHandle.end())
5931- {
5932- result = iter->second;
5933- }
5934-
5935- return result;
5936-}
5937-
5938-LLVoiceClient::sessionState *LLVoiceClient::findSessionBeingCreatedByURI(const std::string &uri)
5939-{
5940- sessionState *result = NULL;
5941- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
5942- {
5943- sessionState *session = *iter;
5944- if(session->mCreateInProgress && (session->mSIPURI == uri))
5945- {
5946- result = session;
5947- break;
5948- }
5949- }
5950-
5951- return result;
5952-}
5953-
5954-LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participant_id)
5955-{
5956- sessionState *result = NULL;
5957-
5958- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
5959- {
5960- sessionState *session = *iter;
5961- if(session->mCallerID == participant_id)
5962- {
5963- result = session;
5964- break;
5965- }
5966- }
5967-
5968- return result;
5969-}
5970-
5971-LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, const std::string &handle)
5972-{
5973- sessionState *result = NULL;
5974-
5975- if(handle.empty())
5976- {
5977- // No handle supplied.
5978- // Check whether there's already a session with this URI
5979- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
5980- {
5981- sessionState *s = *iter;
5982- if((s->mSIPURI == uri) || (s->mAlternateSIPURI == uri))
5983- {
5984- // TODO: I need to think about this logic... it's possible that this case should raise an internal error.
5985- result = s;
5986- break;
5987- }
5988- }
5989- }
5990- else // (!handle.empty())
5991- {
5992- // Check for an existing session with this handle
5993- sessionMap::iterator iter = mSessionsByHandle.find(&handle);
5994-
5995- if(iter != mSessionsByHandle.end())
5996- {
5997- result = iter->second;
5998- }
5999- }
6000-
6001- if(!result)
6002- {
6003- // No existing session found.
6004-
6005- LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL;
6006- result = new sessionState();
6007- result->mSIPURI = uri;
6008- result->mHandle = handle;
6009-
6010- mSessions.insert(result);
6011-
6012- if(!result->mHandle.empty())
6013- {
6014- mSessionsByHandle.insert(sessionMap::value_type(&(result->mHandle), result));
6015- }
6016- }
6017- else
6018- {
6019- // Found an existing session
6020-
6021- if(uri != result->mSIPURI)
6022- {
6023- // TODO: Should this be an internal error?
6024- LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL;
6025- setSessionURI(result, uri);
6026- }
6027-
6028- if(handle != result->mHandle)
6029- {
6030- // TODO: Should this be an internal error?
6031- LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL;
6032- setSessionHandle(result, handle);
6033- }
6034-
6035- LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL;
6036- }
6037-
6038- verifySessionState();
6039-
6040- return result;
6041-}
6042-
6043-void LLVoiceClient::setSessionHandle(sessionState *session, const std::string &handle)
6044-{
6045- // Have to remove the session from the handle-indexed map before changing the handle, or things will break badly.
6046-
6047- if(!session->mHandle.empty())
6048- {
6049- // Remove session from the map if it should have been there.
6050- sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
6051- if(iter != mSessionsByHandle.end())
6052- {
6053- if(iter->second != session)
6054- {
6055- LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL;
6056- }
6057-
6058- mSessionsByHandle.erase(iter);
6059- }
6060- else
6061- {
6062- LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL;
6063- }
6064- }
6065-
6066- session->mHandle = handle;
6067-
6068- if(!handle.empty())
6069- {
6070- mSessionsByHandle.insert(sessionMap::value_type(&(session->mHandle), session));
6071- }
6072-
6073- verifySessionState();
6074-}
6075-
6076-void LLVoiceClient::setSessionURI(sessionState *session, const std::string &uri)
6077-{
6078- // There used to be a map of session URIs to sessions, which made this complex....
6079- session->mSIPURI = uri;
6080-
6081- verifySessionState();
6082-}
6083-
6084-void LLVoiceClient::deleteSession(sessionState *session)
6085-{
6086- // Remove the session from the handle map
6087- if(!session->mHandle.empty())
6088- {
6089- sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
6090- if(iter != mSessionsByHandle.end())
6091- {
6092- if(iter->second != session)
6093- {
6094- LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL
6095- }
6096- mSessionsByHandle.erase(iter);
6097- }
6098- }
6099-
6100- // Remove the session from the URI map
6101- mSessions.erase(session);
6102-
6103- // At this point, the session should be unhooked from all lists and all state should be consistent.
6104- verifySessionState();
6105-
6106- // If this is the current audio session, clean up the pointer which will soon be dangling.
6107- if(mAudioSession == session)
6108- {
6109- mAudioSession = NULL;
6110- mAudioSessionChanged = true;
6111- }
6112-
6113- // ditto for the next audio session
6114- if(mNextAudioSession == session)
6115- {
6116- mNextAudioSession = NULL;
6117- }
6118-
6119- // delete the session
6120- delete session;
6121-}
6122-
6123-void LLVoiceClient::deleteAllSessions()
6124-{
6125- LL_DEBUGS("Voice") << "called" << LL_ENDL;
6126-
6127- while(!mSessions.empty())
6128- {
6129- deleteSession(*(sessionsBegin()));
6130- }
6131-
6132- if(!mSessionsByHandle.empty())
6133- {
6134- LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL
6135- }
6136-}
6137-
6138-void LLVoiceClient::verifySessionState(void)
6139-{
6140- // This is mostly intended for debugging problems with session state management.
6141- LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL;
6142-
6143- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
6144- {
6145- sessionState *session = *iter;
6146-
6147- LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL;
6148-
6149- if(!session->mHandle.empty())
6150- {
6151- // every session with a non-empty handle needs to be in the handle map
6152- sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle));
6153- if(i2 == mSessionsByHandle.end())
6154- {
6155- LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL;
6156- }
6157- else
6158- {
6159- if(i2->second != session)
6160- {
6161- LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL;
6162- }
6163- }
6164- }
6165- }
6166-
6167- // check that every entry in the handle map points to a valid session in the session set
6168- for(sessionMap::iterator iter = mSessionsByHandle.begin(); iter != mSessionsByHandle.end(); iter++)
6169- {
6170- sessionState *session = iter->second;
6171- sessionIterator i2 = mSessions.find(session);
6172- if(i2 == mSessions.end())
6173- {
6174- LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL;
6175- }
6176- else
6177- {
6178- if(session->mHandle != (*i2)->mHandle)
6179- {
6180- LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL;
6181- }
6182- }
6183- }
6184-}
6185-
6186-LLVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
6187- mURI(uri)
6188-{
6189- mOnlineSL = false;
6190- mOnlineSLim = false;
6191- mCanSeeMeOnline = true;
6192- mHasBlockListEntry = false;
6193- mHasAutoAcceptListEntry = false;
6194- mNameResolved = false;
6195- mInVivoxBuddies = false;
6196- mInSLFriends = false;
6197- mNeedsNameUpdate = false;
6198-}
6199-
6200-void LLVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
6201-{
6202- buddyListEntry *buddy = addBuddy(uri, displayName);
6203- buddy->mInVivoxBuddies = true;
6204-}
6205-
6206-LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri)
6207-{
6208- std::string empty;
6209- buddyListEntry *buddy = addBuddy(uri, empty);
6210- if(buddy->mDisplayName.empty())
6211- {
6212- buddy->mNameResolved = false;
6213- }
6214- return buddy;
6215-}
6216-
6217-LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri, const std::string &displayName)
6218-{
6219- buddyListEntry *result = NULL;
6220- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
6221-
6222- if(iter != mBuddyListMap.end())
6223- {
6224- // Found a matching buddy already in the map.
6225- LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
6226- result = iter->second;
6227- }
6228-
6229- if(!result)
6230- {
6231- // participant isn't already in one list or the other.
6232- LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
6233- result = new buddyListEntry(uri);
6234- result->mDisplayName = displayName;
6235-
6236- if(IDFromName(uri, result->mUUID))
6237- {
6238- // Extracted UUID from name successfully.
6239- }
6240- else
6241- {
6242- LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
6243- }
6244-
6245- mBuddyListMap.insert(buddyListMap::value_type(&(result->mURI), result));
6246- }
6247-
6248- return result;
6249-}
6250-
6251-LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const std::string &uri)
6252-{
6253- buddyListEntry *result = NULL;
6254- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
6255- if(iter != mBuddyListMap.end())
6256- {
6257- result = iter->second;
6258- }
6259-
6260- return result;
6261-}
6262-
6263-LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const LLUUID &id)
6264-{
6265- buddyListEntry *result = NULL;
6266- buddyListMap::iterator iter;
6267-
6268- for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
6269+ participantState *participant = findParticipantByID(id);
6270+ if(participant)
6271 {
6272- if(iter->second->mUUID == id)
6273- {
6274- result = iter->second;
6275- break;
6276- }
6277+ result = participant->mServiceType;
6278 }
6279
6280 return result;
6281 }
6282
6283-LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddyByDisplayName(const std::string &name)
6284+std::string LLVoiceClient::getGroupID(const LLUUID& id)
6285 {
6286- buddyListEntry *result = NULL;
6287- buddyListMap::iterator iter;
6288+ std::string result;
6289
6290- for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
6291+ participantState *participant = findParticipantByID(id);
6292+ if(participant)
6293 {
6294- if(iter->second->mDisplayName == name)
6295- {
6296- result = iter->second;
6297- break;
6298- }
6299+ result = participant->mGroupID;
6300 }
6301
6302 return result;
6303 }
6304
6305-void LLVoiceClient::deleteBuddy(const std::string &uri)
6306-{
6307- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
6308- if(iter != mBuddyListMap.end())
6309- {
6310- LL_DEBUGS("Voice") << "deleting buddy " << uri << LL_ENDL;
6311- buddyListEntry *buddy = iter->second;
6312- mBuddyListMap.erase(iter);
6313- delete buddy;
6314- }
6315- else
6316- {
6317- LL_DEBUGS("Voice") << "attempt to delete nonexistent buddy " << uri << LL_ENDL;
6318- }
6319-
6320-}
6321-
6322-void LLVoiceClient::deleteAllBuddies(void)
6323-{
6324- while(!mBuddyListMap.empty())
6325- {
6326- deleteBuddy(*(mBuddyListMap.begin()->first));
6327- }
6328-
6329- // Don't want to correlate with friends list when we've emptied the buddy list.
6330- mBuddyListMapPopulated = false;
6331-
6332- // Don't want to correlate with friends list when we've reset the block rules.
6333- mBlockRulesListReceived = false;
6334- mAutoAcceptRulesListReceived = false;
6335-}
6336-
6337-void LLVoiceClient::deleteAllBlockRules(void)
6338-{
6339- // Clear the block list entry flags from all local buddy list entries
6340- buddyListMap::iterator buddy_it;
6341- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
6342- {
6343- buddy_it->second->mHasBlockListEntry = false;
6344- }
6345-}
6346-
6347-void LLVoiceClient::deleteAllAutoAcceptRules(void)
6348-{
6349- // Clear the auto-accept list entry flags from all local buddy list entries
6350- buddyListMap::iterator buddy_it;
6351- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
6352- {
6353- buddy_it->second->mHasAutoAcceptListEntry = false;
6354- }
6355-}
6356-
6357-void LLVoiceClient::addBlockRule(const std::string &blockMask, const std::string &presenceOnly)
6358-{
6359- buddyListEntry *buddy = NULL;
6360-
6361- // blockMask is the SIP URI of a friends list entry
6362- buddyListMap::iterator iter = mBuddyListMap.find(&blockMask);
6363- if(iter != mBuddyListMap.end())
6364- {
6365- LL_DEBUGS("Voice") << "block list entry for " << blockMask << LL_ENDL;
6366- buddy = iter->second;
6367- }
6368-
6369- if(buddy == NULL)
6370- {
6371- LL_DEBUGS("Voice") << "block list entry for unknown buddy " << blockMask << LL_ENDL;
6372- buddy = addBuddy(blockMask);
6373- }
6374-
6375- if(buddy != NULL)
6376- {
6377- buddy->mHasBlockListEntry = true;
6378- }
6379-}
6380-
6381-void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy)
6382-{
6383- buddyListEntry *buddy = NULL;
6384-
6385- // blockMask is the SIP URI of a friends list entry
6386- buddyListMap::iterator iter = mBuddyListMap.find(&autoAcceptMask);
6387- if(iter != mBuddyListMap.end())
6388- {
6389- LL_DEBUGS("Voice") << "auto-accept list entry for " << autoAcceptMask << LL_ENDL;
6390- buddy = iter->second;
6391- }
6392-
6393- if(buddy == NULL)
6394- {
6395- LL_DEBUGS("Voice") << "auto-accept list entry for unknown buddy " << autoAcceptMask << LL_ENDL;
6396- buddy = addBuddy(autoAcceptMask);
6397- }
6398-
6399- if(buddy != NULL)
6400- {
6401- buddy->mHasAutoAcceptListEntry = true;
6402- }
6403-}
6404-
6405-void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
6406-{
6407- // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done.
6408- mBlockRulesListReceived = true;
6409-}
6410-
6411-void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString)
6412+BOOL LLVoiceClient::getAreaVoiceDisabled()
6413 {
6414- // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done.
6415- mAutoAcceptRulesListReceived = true;
6416+ return mAreaVoiceDisabled;
6417 }
6418
6419 void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
6420 {
6421- mParticipantObservers.insert(observer);
6422+ mObservers.insert(observer);
6423 }
6424
6425 void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
6426 {
6427- mParticipantObservers.erase(observer);
6428+ mObservers.erase(observer);
6429 }
6430
6431-void LLVoiceClient::notifyParticipantObservers()
6432+void LLVoiceClient::notifyObservers()
6433 {
6434- for (observer_set_t::iterator it = mParticipantObservers.begin();
6435- it != mParticipantObservers.end();
6436+ for (observer_set_t::iterator it = mObservers.begin();
6437+ it != mObservers.end();
6438 )
6439 {
6440 LLVoiceClientParticipantObserver* observer = *it;
6441 observer->onChange();
6442 // In case onChange() deleted an entry.
6443- it = mParticipantObservers.upper_bound(observer);
6444+ it = mObservers.upper_bound(observer);
6445 }
6446 }
6447
6448-void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
6449+void LLVoiceClient::addStatusObserver(LLVoiceClientStatusObserver* observer)
6450 {
6451 mStatusObservers.insert(observer);
6452 }
6453
6454-void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
6455+void LLVoiceClient::removeStatusObserver(LLVoiceClientStatusObserver* observer)
6456 {
6457 mStatusObservers.erase(observer);
6458 }
6459
6460 void LLVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status)
6461 {
6462- if(mAudioSession)
6463+ if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
6464 {
6465- if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
6466- {
6467- switch(mAudioSession->mErrorStatusCode)
6468- {
6469- case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
6470- case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
6471- case 20715:
6472- //invalid channel, we may be using a set of poorly cached
6473- //info
6474- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
6475- break;
6476- case 1009:
6477- //invalid username and password
6478- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
6479- break;
6480- }
6481-
6482- // Reset the error code to make sure it won't be reused later by accident.
6483- mAudioSession->mErrorStatusCode = 0;
6484- }
6485- else if(status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL)
6486+ switch(mVivoxErrorStatusCode)
6487 {
6488- switch(mAudioSession->mErrorStatusCode)
6489- {
6490- case 404: // NOT_FOUND
6491- case 480: // TEMPORARILY_UNAVAILABLE
6492- case 408: // REQUEST_TIMEOUT
6493- // call failed because other user was not available
6494- // treat this as an error case
6495- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
6496-
6497- // Reset the error code to make sure it won't be reused later by accident.
6498- mAudioSession->mErrorStatusCode = 0;
6499- break;
6500- }
6501+ case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
6502+ case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
6503+ case 20715:
6504+ //invalid channel, we may be using a set of poorly cached
6505+ //info
6506+ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
6507+ break;
6508+ case 1009:
6509+ //invalid username and password
6510+ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
6511+ break;
6512 }
6513+
6514+ // Reset the error code to make sure it won't be reused later by accident.
6515+ mVivoxErrorStatusCode = 0;
6516 }
6517-
6518- LL_DEBUGS("Voice")
6519- << " " << LLVoiceClientStatusObserver::status2string(status)
6520- << ", session URI " << getAudioSessionURI()
6521- << (inSpatialChannel()?", proximal is true":", proximal is false")
6522- << LL_ENDL;
6523+
6524+ if (status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL
6525+ //NOT_FOUND || TEMPORARILY_UNAVAILABLE || REQUEST_TIMEOUT
6526+ && (mVivoxErrorStatusCode == 404 || mVivoxErrorStatusCode == 480 || mVivoxErrorStatusCode == 408))
6527+ {
6528+ // call failed because other user was not available
6529+ // treat this as an error case
6530+ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
6531+
6532+ // Reset the error code to make sure it won't be reused later by accident.
6533+ mVivoxErrorStatusCode = 0;
6534+ }
6535+
6536+ LL_DEBUGS("Voice") << " " << LLVoiceClientStatusObserver::status2string(status) << ", session URI " << mSessionURI << LL_ENDL;
6537
6538 for (status_observer_set_t::iterator it = mStatusObservers.begin();
6539 it != mStatusObservers.end();
6540 )
6541 {
6542 LLVoiceClientStatusObserver* observer = *it;
6543- observer->onChange(status, getAudioSessionURI(), inSpatialChannel());
6544+ observer->onChange(status, mSessionURI, !mNonSpatialChannel);
6545 // In case onError() deleted an entry.
6546 it = mStatusObservers.upper_bound(observer);
6547 }
6548
6549 }
6550
6551-void LLVoiceClient::addObserver(LLFriendObserver* observer)
6552-{
6553- mFriendObservers.insert(observer);
6554-}
6555-
6556-void LLVoiceClient::removeObserver(LLFriendObserver* observer)
6557-{
6558- mFriendObservers.erase(observer);
6559-}
6560-
6561-void LLVoiceClient::notifyFriendObservers()
6562-{
6563- for (friend_observer_set_t::iterator it = mFriendObservers.begin();
6564- it != mFriendObservers.end();
6565- )
6566- {
6567- LLFriendObserver* observer = *it;
6568- it++;
6569- // The only friend-related thing we notify on is online/offline transitions.
6570- observer->changed(LLFriendObserver::ONLINE);
6571- }
6572-}
6573-
6574-void LLVoiceClient::lookupName(const LLUUID &id)
6575-{
6576- gCacheName->getName(id, onAvatarNameLookup);
6577-}
6578-
6579 //static
6580-void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
6581-{
6582- if(gVoiceClient)
6583- {
6584- std::string name = llformat("%s %s", first.c_str(), last.c_str());
6585- gVoiceClient->avatarNameResolved(id, name);
6586- }
6587-}
6588+// void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
6589+// {
6590+// participantState* statep = gVoiceClient->findParticipantByID(id);
6591
6592-void LLVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
6593-{
6594- // If the avatar whose name just resolved is on our friends list, resync the friends list.
6595- if(LLAvatarTracker::instance().getBuddyInfo(id) != NULL)
6596- {
6597- mFriendsListDirty = true;
6598- }
6599+// if (statep)
6600+// {
6601+// statep->mDisplayName = first + " " + last;
6602+// }
6603
6604- // Iterate over all sessions.
6605- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
6606- {
6607- sessionState *session = *iter;
6608-
6609- // Check for this user as a participant in this session
6610- participantState *participant = session->findParticipantByID(id);
6611- if(participant)
6612- {
6613- // Found -- fill in the name
6614- participant->mAccountName = name;
6615- // and post a "participants updated" message to listeners later.
6616- session->mParticipantsChanged = true;
6617- }
6618-
6619- // Check whether this is a p2p session whose caller name just resolved
6620- if(session->mCallerID == id)
6621- {
6622- // this session's "caller ID" just resolved. Fill in the name.
6623- session->mName = name;
6624- if(session->mTextInvitePending)
6625- {
6626- session->mTextInvitePending = false;
6627-
6628- // We don't need to call gIMMgr->addP2PSession() here. The first incoming message will create the panel.
6629- }
6630- if(session->mVoiceInvitePending)
6631- {
6632- session->mVoiceInvitePending = false;
6633-
6634- gIMMgr->inviteToSession(
6635- session->mIMSessionID,
6636- session->mName,
6637- session->mCallerID,
6638- session->mName,
6639- IM_SESSION_P2P_INVITE,
6640- LLIMMgr::INVITATION_TYPE_VOICE,
6641- session->mHandle,
6642- session->mSIPURI);
6643- }
6644-
6645- }
6646- }
6647-}
6648+// gVoiceClient->notifyObservers();
6649+// }
6650
6651 class LLViewerParcelVoiceInfo : public LLHTTPNode
6652 {
6653diff --git a/linden/indra/newview/llvoiceclient.h b/linden/indra/newview/llvoiceclient.h
6654index 13dd974..d0b7839 100644
6655--- a/linden/indra/newview/llvoiceclient.h
6656+++ b/linden/indra/newview/llvoiceclient.h
6657@@ -41,7 +41,6 @@ class LLVivoxProtocolParser;
6658 #include "v3math.h"
6659 #include "llframetimer.h"
6660 #include "llviewerregion.h"
6661-#include "llcallingcard.h" // for LLFriendObserver
6662
6663 class LLVoiceClientParticipantObserver
6664 {
6665@@ -92,10 +91,41 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
6666
6667 public:
6668
6669+ enum serviceType
6670+ {
6671+ serviceTypeUnknown, // Unknown, returned if no data on the avatar is available
6672+ serviceTypeA, // spatialized local chat
6673+ serviceTypeB, // remote multi-party chat
6674+ serviceTypeC // one-to-one and small group chat
6675+ };
6676 static F32 OVERDRIVEN_POWER_LEVEL;
6677
6678 void updateSettings(); // call after loading settings and whenever they change
6679
6680+ /////////////////////////////
6681+ // session control messages
6682+ void connect();
6683+
6684+ void connectorCreate();
6685+ void connectorShutdown();
6686+
6687+ void requestVoiceAccountProvision(S32 retries = 3);
6688+ void userAuthorized(
6689+ const std::string& firstName,
6690+ const std::string& lastName,
6691+ const LLUUID &agentID);
6692+ void login(const std::string& accountName, const std::string &password);
6693+ void loginSendMessage();
6694+ void logout();
6695+ void logoutSendMessage();
6696+
6697+ void channelGetListSendMessage();
6698+ void sessionCreateSendMessage();
6699+ void sessionConnectSendMessage();
6700+ void sessionTerminate();
6701+ void sessionTerminateSendMessage();
6702+ void sessionTerminateByHandle(std::string &sessionHandle);
6703+
6704 void getCaptureDevicesSendMessage();
6705 void getRenderDevicesSendMessage();
6706
6707@@ -140,32 +170,23 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
6708
6709 /////////////////////////////
6710 // Response/Event handlers
6711- void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
6712- void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases);
6713- void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
6714- void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
6715- void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString);
6716+ void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle);
6717+ void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle);
6718+ void channelGetListResponse(int statusCode, std::string &statusString);
6719+ void sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle);
6720+ void sessionConnectResponse(int statusCode, std::string &statusString);
6721+ void sessionTerminateResponse(int statusCode, std::string &statusString);
6722 void logoutResponse(int statusCode, std::string &statusString);
6723 void connectorShutdownResponse(int statusCode, std::string &statusString);
6724
6725- void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
6726- void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);
6727- void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming);
6728- void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString);
6729- void sessionGroupAddedEvent(std::string &sessionGroupHandle);
6730- void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle);
6731- void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType);
6732- void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString);
6733- void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
6734+ void loginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
6735+ void sessionNewEvent(std::string &accountHandle, std::string &eventSessionHandle, int state, std::string &nameString, std::string &uriString);
6736+ void sessionStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, std::string &sessionHandle, int state, bool isChannel, std::string &nameString);
6737+ void participantStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, int state, std::string &nameString, std::string &displayNameString, int participantType);
6738+ void participantPropertiesEvent(std::string &uriString, int statusCode, std::string &statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
6739 void auxAudioPropertiesEvent(F32 energy);
6740- void buddyPresenceEvent(std::string &uriString, std::string &alias, std::string &statusString, std::string &applicationString);
6741- void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
6742- void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType);
6743- void subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType);
6744-
6745- void buddyListChanged();
6746+
6747 void muteListChanged();
6748- void updateFriends(U32 mask);
6749
6750 /////////////////////////////
6751 // Sending updates of current state
6752@@ -189,6 +210,7 @@ static void updatePosition(void);
6753 void setVoiceVolume(F32 volume);
6754 void setMicGain(F32 volume);
6755 void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
6756+ void setVivoxDebugServerName(std::string &serverName);
6757 void setLipSyncEnabled(BOOL enabled);
6758 BOOL lipSyncEnabled();
6759
6760@@ -203,261 +225,57 @@ static void updatePosition(void);
6761 BOOL getIsSpeaking(const LLUUID& id);
6762 BOOL getIsModeratorMuted(const LLUUID& id);
6763 F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
6764+ BOOL getPTTPressed(const LLUUID& id); // This is the inverse of the "locally muted" property.
6765 BOOL getOnMuteList(const LLUUID& id);
6766 F32 getUserVolume(const LLUUID& id);
6767 std::string getDisplayName(const LLUUID& id);
6768
6769 // MBW -- XXX -- Not sure how to get this data out of the TVC
6770 BOOL getUsingPTT(const LLUUID& id);
6771+ serviceType getServiceType(const LLUUID& id); // type of chat the user is involved in (see bHear scope doc for definitions of A/B/C)
6772 std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable)
6773
6774 /////////////////////////////
6775 BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled.
6776 // Use this to determine whether to show a "no speech" icon in the menu bar.
6777-
6778- /////////////////////////////
6779- // Recording controls
6780- void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
6781- void recordingLoopSave(const std::string& filename);
6782- void recordingStop();
6783-
6784- // Playback controls
6785- void filePlaybackStart(const std::string& filename);
6786- void filePlaybackStop();
6787- void filePlaybackSetPaused(bool paused);
6788- void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
6789-
6790-
6791- // This is used by the string-keyed maps below, to avoid storing the string twice.
6792- // The 'const std::string *' in the key points to a string actually stored in the object referenced by the map.
6793- // The add and delete operations for each map allocate and delete in the right order to avoid dangling references.
6794- // The default compare operation would just compare pointers, which is incorrect, so they must use this comparitor instead.
6795- struct stringMapComparitor
6796- {
6797- bool operator()(const std::string* a, const std::string * b) const
6798- {
6799- return a->compare(*b) < 0;
6800- }
6801- };
6802
6803- struct uuidMapComparitor
6804- {
6805- bool operator()(const LLUUID* a, const LLUUID * b) const
6806- {
6807- return *a < *b;
6808- }
6809- };
6810-
6811 struct participantState
6812 {
6813 public:
6814 participantState(const std::string &uri);
6815-
6816- bool updateMuteState();
6817-
6818 std::string mURI;
6819- LLUUID mAvatarID;
6820- std::string mAccountName;
6821+ std::string mName;
6822 std::string mDisplayName;
6823+ bool mPTT;
6824+ bool mIsSpeaking;
6825+ bool mIsModeratorMuted;
6826 LLFrameTimer mSpeakingTimeout;
6827 F32 mLastSpokeTimestamp;
6828 F32 mPower;
6829 int mVolume;
6830+ serviceType mServiceType;
6831 std::string mGroupID;
6832- int mUserVolume;
6833- bool mPTT;
6834- bool mIsSpeaking;
6835- bool mIsModeratorMuted;
6836 bool mOnMuteList; // true if this avatar is on the user's mute list (and should be muted)
6837+ int mUserVolume;
6838 bool mVolumeDirty; // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
6839 bool mAvatarIDValid;
6840- bool mIsSelf;
6841- };
6842- typedef std::map<const std::string *, participantState*, stringMapComparitor> participantMap;
6843-
6844- typedef std::map<const LLUUID *, participantState*, uuidMapComparitor> participantUUIDMap;
6845-
6846- enum streamState
6847- {
6848- streamStateUnknown = 0,
6849- streamStateIdle = 1,
6850- streamStateConnected = 2,
6851- streamStateRinging = 3,
6852+ LLUUID mAvatarID;
6853 };
6854+ typedef std::map<std::string, participantState*> participantMap;
6855
6856- struct sessionState
6857- {
6858- public:
6859- sessionState();
6860- ~sessionState();
6861-
6862- participantState *addParticipant(const std::string &uri);
6863- // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
6864- // Take care not to use the pointer again after that.
6865- void removeParticipant(participantState *participant);
6866- void removeAllParticipants();
6867-
6868- participantState *findParticipant(const std::string &uri);
6869- participantState *findParticipantByID(const LLUUID& id);
6870-
6871- std::string mHandle;
6872- std::string mGroupHandle;
6873- std::string mSIPURI;
6874- std::string mAlias;
6875- std::string mName;
6876- std::string mAlternateSIPURI;
6877- std::string mHash; // Channel password
6878- std::string mErrorStatusString;
6879- std::queue<std::string> mTextMsgQueue;
6880-
6881- LLUUID mIMSessionID;
6882- LLUUID mCallerID;
6883- int mErrorStatusCode;
6884- int mMediaStreamState;
6885- int mTextStreamState;
6886- bool mCreateInProgress; // True if a Session.Create has been sent for this session and no response has been received yet.
6887- bool mMediaConnectInProgress; // True if a Session.MediaConnect has been sent for this session and no response has been received yet.
6888- bool mVoiceInvitePending; // True if a voice invite is pending for this session (usually waiting on a name lookup)
6889- bool mTextInvitePending; // True if a text invite is pending for this session (usually waiting on a name lookup)
6890- bool mSynthesizedCallerID; // True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup.
6891- bool mIsChannel; // True for both group and spatial channels (false for p2p, PSTN)
6892- bool mIsSpatial; // True for spatial channels
6893- bool mIsP2P;
6894- bool mIncoming;
6895- bool mVoiceEnabled;
6896- bool mReconnect; // Whether we should try to reconnect to this session if it's dropped
6897- // Set to true when the mute state of someone in the participant list changes.
6898- // The code will have to walk the list to find the changed participant(s).
6899- bool mVolumeDirty;
6900-
6901- bool mParticipantsChanged;
6902- participantMap mParticipantsByURI;
6903- participantUUIDMap mParticipantsByUUID;
6904- };
6905-
6906+ participantState *findParticipant(const std::string &uri);
6907+ participantState *findParticipantByAvatar(LLVOAvatar *avatar);
6908 participantState *findParticipantByID(const LLUUID& id);
6909- participantMap *getParticipantList(void);
6910-
6911- typedef std::map<const std::string*, sessionState*, stringMapComparitor> sessionMap;
6912- typedef std::set<sessionState*> sessionSet;
6913-
6914- typedef sessionSet::iterator sessionIterator;
6915- sessionIterator sessionsBegin(void);
6916- sessionIterator sessionsEnd(void);
6917-
6918- sessionState *findSession(const std::string &handle);
6919- sessionState *findSessionBeingCreatedByURI(const std::string &uri);
6920- sessionState *findSession(const LLUUID &participant_id);
6921- sessionState *findSessionByCreateID(const std::string &create_id);
6922-
6923- sessionState *addSession(const std::string &uri, const std::string &handle = LLStringUtil::null);
6924- void setSessionHandle(sessionState *session, const std::string &handle = LLStringUtil::null);
6925- void setSessionURI(sessionState *session, const std::string &uri);
6926- void deleteSession(sessionState *session);
6927- void deleteAllSessions(void);
6928-
6929- void verifySessionState(void);
6930-
6931- void joinedAudioSession(sessionState *session);
6932- void leftAudioSession(sessionState *session);
6933-
6934- // This is called in several places where the session _may_ need to be deleted.
6935- // It contains logic for whether to delete the session or keep it around.
6936- void reapSession(sessionState *session);
6937-
6938- // Returns true if the session seems to indicate we've moved to a region on a different voice server
6939- bool sessionNeedsRelog(sessionState *session);
6940-
6941- struct buddyListEntry
6942- {
6943- buddyListEntry(const std::string &uri);
6944- std::string mURI;
6945- std::string mDisplayName;
6946- LLUUID mUUID;
6947- bool mOnlineSL;
6948- bool mOnlineSLim;
6949- bool mCanSeeMeOnline;
6950- bool mHasBlockListEntry;
6951- bool mHasAutoAcceptListEntry;
6952- bool mNameResolved;
6953- bool mInSLFriends;
6954- bool mInVivoxBuddies;
6955- bool mNeedsNameUpdate;
6956- };
6957-
6958- typedef std::map<const std::string*, buddyListEntry*, stringMapComparitor> buddyListMap;
6959
6960- // This should be called when parsing a buddy list entry sent by SLVoice.
6961- void processBuddyListEntry(const std::string &uri, const std::string &displayName);
6962-
6963- buddyListEntry *addBuddy(const std::string &uri);
6964- buddyListEntry *addBuddy(const std::string &uri, const std::string &displayName);
6965- buddyListEntry *findBuddy(const std::string &uri);
6966- buddyListEntry *findBuddy(const LLUUID &id);
6967- buddyListEntry *findBuddyByDisplayName(const std::string &name);
6968- void deleteBuddy(const std::string &uri);
6969- void deleteAllBuddies(void);
6970-
6971- void deleteAllBlockRules(void);
6972- void addBlockRule(const std::string &blockMask, const std::string &presenceOnly);
6973- void deleteAllAutoAcceptRules(void);
6974- void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy);
6975- void accountListBlockRulesResponse(int statusCode, const std::string &statusString);
6976- void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);
6977-
6978- /////////////////////////////
6979- // session control messages
6980- void connectorCreate();
6981- void connectorShutdown();
6982-
6983- void requestVoiceAccountProvision(S32 retries = 3);
6984- void userAuthorized(
6985- const std::string& firstName,
6986- const std::string& lastName,
6987- const LLUUID &agentID);
6988- void login(
6989- const std::string& account_name,
6990- const std::string& password,
6991- const std::string& voice_sip_uri_hostname,
6992- const std::string& voice_account_server_uri);
6993- void loginSendMessage();
6994- void logout();
6995- void logoutSendMessage();
6996-
6997- void accountListBlockRulesSendMessage();
6998- void accountListAutoAcceptRulesSendMessage();
6999-
7000- void sessionGroupCreateSendMessage();
7001- void sessionCreateSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
7002- void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
7003- void sessionMediaConnectSendMessage(sessionState *session); // just joins the audio session
7004- void sessionTextConnectSendMessage(sessionState *session); // just joins the text session
7005- void sessionTerminateSendMessage(sessionState *session);
7006- void sessionMediaDisconnectSendMessage(sessionState *session);
7007- void sessionTextDisconnectSendMessage(sessionState *session);
7008+ participantMap *getParticipantList(void);
7009
7010- // Pokes the state machine to leave the audio session next time around.
7011- void sessionTerminate();
7012-
7013- // Pokes the state machine to shut down the connector and restart it.
7014- void requestRelog();
7015-
7016- // Does the actual work to get out of the audio session
7017- void leaveAudioSession();
7018-
7019 void addObserver(LLVoiceClientParticipantObserver* observer);
7020 void removeObserver(LLVoiceClientParticipantObserver* observer);
7021
7022- void addObserver(LLVoiceClientStatusObserver* observer);
7023- void removeObserver(LLVoiceClientStatusObserver* observer);
7024-
7025- void addObserver(LLFriendObserver* observer);
7026- void removeObserver(LLFriendObserver* observer);
7027-
7028- void lookupName(const LLUUID &id);
7029- static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
7030- void avatarNameResolved(const LLUUID &id, const std::string &name);
7031+ void addStatusObserver(LLVoiceClientStatusObserver* observer);
7032+ void removeStatusObserver(LLVoiceClientStatusObserver* observer);
7033
7034+// static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
7035 typedef std::vector<std::string> deviceList;
7036
7037 deviceList *getCaptureDevices();
7038@@ -469,16 +287,8 @@ static void updatePosition(void);
7039 void setSpatialChannel(
7040 const std::string &uri,
7041 const std::string &credentials);
7042- // start a voice session with the specified user
7043- void callUser(const LLUUID &uuid);
7044-
7045- // Send a text message to the specified user, initiating the session if necessary.
7046- bool sendTextMessage(const LLUUID& participant_id, const std::string& message);
7047-
7048- // close any existing text IM session with the specified user
7049- void endUserIMSession(const LLUUID &uuid);
7050-
7051- bool answerInvite(std::string &sessionHandle);
7052+ void callUser(LLUUID &uuid);
7053+ void answerInvite(std::string &sessionHandle, LLUUID& other_user_id);
7054 void declineInvite(std::string &sessionHandle);
7055 void leaveNonSpatialChannel();
7056
7057@@ -491,37 +301,33 @@ static void updatePosition(void);
7058 bool inProximalChannel();
7059
7060 std::string sipURIFromID(const LLUUID &id);
7061-
7062- // Returns true if the indicated user is online via SIP presence according to SLVoice.
7063- // Note that we only get SIP presence data for other users that are in our vivox buddy list.
7064- bool isOnlineSIP(const LLUUID &id);
7065-
7066+
7067 private:
7068
7069 // internal state for a simple state machine. This is used to deal with the asynchronous nature of some of the messages.
7070 // Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string().
7071 enum state
7072 {
7073- stateDisableCleanup,
7074 stateDisabled, // Voice is turned off.
7075 stateStart, // Class is initialized, socket is created
7076 stateDaemonLaunched, // Daemon has been launched
7077 stateConnecting, // connect() call has been issued
7078- stateConnected, // connection to the daemon has been made, send some initial setup commands.
7079 stateIdle, // socket is connected, ready for messaging
7080- stateMicTuningStart,
7081- stateMicTuningRunning,
7082- stateMicTuningStop,
7083 stateConnectorStart, // connector needs to be started
7084 stateConnectorStarting, // waiting for connector handle
7085 stateConnectorStarted, // connector handle received
7086+ stateMicTuningNoLogin, // mic tuning before login
7087 stateLoginRetry, // need to retry login (failed due to changing password)
7088 stateLoginRetryWait, // waiting for retry timer
7089 stateNeedsLogin, // send login request
7090 stateLoggingIn, // waiting for account handle
7091 stateLoggedIn, // account handle received
7092- stateCreatingSessionGroup, // Creating the main session group
7093 stateNoChannel, //
7094+ stateMicTuningStart,
7095+ stateMicTuningRunning,
7096+ stateMicTuningStop,
7097+ stateSessionCreate, // need to send Session.Create command
7098+ stateSessionConnect, // need to send Session.Connect command
7099 stateJoiningSession, // waiting for session handle
7100 stateSessionJoined, // session handle received
7101 stateRunning, // in session, steady state
7102@@ -548,7 +354,7 @@ static void updatePosition(void);
7103
7104 state mState;
7105 bool mSessionTerminateRequested;
7106- bool mRelogRequested;
7107+ bool mNonSpatialChannel;
7108
7109 void setState(state inState);
7110 state getState(void) { return mState; };
7111@@ -571,7 +377,18 @@ static void updatePosition(void);
7112 std::string mAccountDisplayName;
7113 std::string mAccountFirstName;
7114 std::string mAccountLastName;
7115-
7116+
7117+ std::string mNextP2PSessionURI; // URI of the P2P session to join next
7118+ std::string mNextSessionURI; // URI of the session to join next
7119+ std::string mNextSessionHandle; // Session handle of the session to join next
7120+ std::string mNextSessionHash; // Password hash for the session to join next
7121+ bool mNextSessionSpatial; // Will next session be a spatial chat?
7122+ bool mNextSessionNoReconnect; // Next session should not auto-reconnect (i.e. user -> user chat)
7123+ bool mNextSessionResetOnClose; // If this is true, go back to spatial chat when the next session terminates.
7124+
7125+ std::string mSessionStateEventHandle; // session handle received in SessionStateChangeEvents
7126+ std::string mSessionStateEventURI; // session URI received in SessionStateChangeEvents
7127+
7128 bool mTuningMode;
7129 float mTuningEnergy;
7130 std::string mTuningAudioFile;
7131@@ -582,40 +399,32 @@ static void updatePosition(void);
7132 state mTuningExitState; // state to return to when we leave tuning mode.
7133
7134 std::string mSpatialSessionURI;
7135- std::string mSpatialSessionCredentials;
7136-
7137- std::string mMainSessionGroupHandle; // handle of the "main" session group.
7138+
7139+ bool mSessionResetOnClose;
7140+
7141+ int mVivoxErrorStatusCode;
7142+ std::string mVivoxErrorStatusString;
7143
7144 std::string mChannelName; // Name of the channel to be looked up
7145 bool mAreaVoiceDisabled;
7146- sessionState *mAudioSession; // Session state for the current audio session
7147- bool mAudioSessionChanged; // set to true when the above pointer gets changed, so observers can be notified.
7148-
7149- sessionState *mNextAudioSession; // Session state for the audio session we're trying to join
7150-
7151-// std::string mSessionURI; // URI of the session we're in.
7152-// std::string mSessionHandle; // returned by ?
7153+ std::string mSessionURI; // URI of the session we're in.
7154+ bool mSessionP2P; // true if this session is a p2p call
7155
7156 S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings
7157 std::string mCurrentRegionName; // Used to detect parcel boundary crossings
7158
7159 std::string mConnectorHandle; // returned by "Create Connector" message
7160 std::string mAccountHandle; // returned by login message
7161- int mNumberOfAliases;
7162+ std::string mSessionHandle; // returned by ?
7163 U32 mCommandCookie;
7164
7165- std::string mVoiceAccountServerURI;
7166- std::string mVoiceSIPURIHostName;
7167+ std::string mAccountServerName;
7168+ std::string mAccountServerURI;
7169
7170 int mLoginRetryCount;
7171
7172- sessionMap mSessionsByHandle; // Active sessions, indexed by session handle. Sessions which are being initiated may not be in this map.
7173- sessionSet mSessions; // All sessions, not indexed. This is the canonical session list.
7174-
7175- bool mBuddyListMapPopulated;
7176- bool mBlockRulesListReceived;
7177- bool mAutoAcceptRulesListReceived;
7178- buddyListMap mBuddyListMap;
7179+ participantMap mParticipantMap;
7180+ bool mParticipantMapChanged;
7181
7182 deviceList mCaptureDevices;
7183 deviceList mRenderDevices;
7184@@ -625,41 +434,40 @@ static void updatePosition(void);
7185 bool mCaptureDeviceDirty;
7186 bool mRenderDeviceDirty;
7187
7188+ participantState *addParticipant(const std::string &uri);
7189+ // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
7190+ // Take care not to use the pointer again after that.
7191+ void removeParticipant(participantState *participant);
7192+ void removeAllParticipants();
7193+
7194+ void updateMuteState(participantState *participant);
7195+
7196+ typedef std::map<std::string, std::string> channelMap;
7197+ channelMap mChannelMap;
7198+
7199+ // These are used by the parser when processing a channel list response.
7200+ void clearChannelMap(void);
7201+ void addChannelMapEntry(std::string &name, std::string &uri);
7202+ std::string findChannelURI(std::string &name);
7203+
7204 // This should be called when the code detects we have changed parcels.
7205 // It initiates the call to the server that gets the parcel channel.
7206 void parcelChanged();
7207
7208- void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
7209- void joinSession(sessionState *session);
7210+ void switchChannel(std::string uri = std::string(), bool spatial = true, bool noReconnect = false, std::string hash = "");
7211+ void joinSession(std::string handle, std::string uri);
7212
7213-static std::string nameFromAvatar(LLVOAvatar *avatar);
7214-static std::string nameFromID(const LLUUID &id);
7215-static bool IDFromName(const std::string name, LLUUID &uuid);
7216-static std::string displayNameFromAvatar(LLVOAvatar *avatar);
7217+ std::string nameFromAvatar(LLVOAvatar *avatar);
7218+ std::string nameFromID(const LLUUID &id);
7219+ bool IDFromName(const std::string name, LLUUID &uuid);
7220+ std::string displayNameFromAvatar(LLVOAvatar *avatar);
7221 std::string sipURIFromAvatar(LLVOAvatar *avatar);
7222 std::string sipURIFromName(std::string &name);
7223-
7224- // Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
7225-static std::string nameFromsipURI(const std::string &uri);
7226-
7227- bool inSpatialChannel(void);
7228- std::string getAudioSessionURI();
7229- std::string getAudioSessionHandle();
7230
7231 void sendPositionalUpdate(void);
7232
7233 void buildSetCaptureDevice(std::ostringstream &stream);
7234 void buildSetRenderDevice(std::ostringstream &stream);
7235- void buildLocalAudioUpdates(std::ostringstream &stream);
7236-
7237- void clearAllLists();
7238- void checkFriend(const LLUUID& id);
7239- void sendFriendsListUpdates();
7240-
7241- // start a text IM session with the specified user
7242- // This will be asynchronous, the session may be established at a future time.
7243- sessionState* startUserIMSession(const LLUUID& uuid);
7244- void sendQueuedTextMessages(sessionState *session);
7245
7246 void enforceTether(void);
7247
7248@@ -683,9 +491,10 @@ static std::string nameFromsipURI(const std::string &uri);
7249 bool mPTTIsToggle;
7250 bool mUserPTTState;
7251 bool mMuteMic;
7252-
7253- // Set to true when the friends list is known to have changed.
7254- bool mFriendsListDirty;
7255+
7256+ // Set to true when the mute state of someone in the participant list changes.
7257+ // The code will have to walk the list to find the changed participant(s).
7258+ bool mVolumeDirty;
7259
7260 enum
7261 {
7262@@ -713,18 +522,14 @@ static std::string nameFromsipURI(const std::string &uri);
7263 BOOL mLipSyncEnabled;
7264
7265 typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
7266- observer_set_t mParticipantObservers;
7267+ observer_set_t mObservers;
7268
7269- void notifyParticipantObservers();
7270+ void notifyObservers();
7271
7272 typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
7273 status_observer_set_t mStatusObservers;
7274
7275 void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
7276-
7277- typedef std::set<LLFriendObserver*> friend_observer_set_t;
7278- friend_observer_set_t mFriendObservers;
7279- void notifyFriendObservers();
7280 };
7281
7282 extern LLVoiceClient *gVoiceClient;
diff --git a/stack_trace.log b/stack_trace.log
new file mode 100644
index 0000000..b04e344
--- /dev/null
+++ b/stack_trace.log
@@ -0,0 +1,32 @@
10: ELF(do_elfio_glibc_backtrace()+0x424) [0x9962c13]
21: ELF(LLAppViewerLinux::handleSyncCrashTrace()+0xb) [0x9963533]
32: ELF(LLAppViewer::handleSyncViewerCrash()+0x20) [0x85181a2]
43: ELF(LLApp::runSyncErrorHandler()+0x16) [0x9e7d384]
54: ELF(LLApp::setError()+0x17) [0x9e7d40d]
65: ELF(default_unix_signal_handler(int, siginfo*, void*)+0xd22) [0x9e7f08e]
76: [0xb807640c]
87: /usr/lib/libstdc++.so.6(_ZNSs6assignERKSs+0x2b) [0xb617825b]
98: /usr/lib/libstdc++.so.6(_ZNSsaSERKSs+0x24) [0xb6178334]
109: ELF(attach_label(std::string&, void*)+0x32) [0x9563d7b]
1110: ELF(LLMenuItemCallGL::buildDrawLabel()+0x232) [0x9c2d012]
1211: ELF(LLMenuGL::arrange()+0xb07) [0x9c31719]
1312: ELF(LLMenuGL::append(LLMenuItemGL*)+0x4c) [0x9c280ca]
1413: ELF(LLMenuGL::arrange()+0x6b3) [0x9c312c5]
1514: ELF(LLMenuGL::append(LLMenuItemGL*)+0x4c) [0x9c280ca]
1615: ELF(LLVOAvatar::buildCharacter()+0x3a8e) [0x974689c]
1716: ELF(LLVOAvatar::LLVOAvatar(LLUUID const&, unsigned char, LLViewerRegion*)+0x4140) [0x97566e4]
1817: ELF(LLViewerObject::createObject(LLUUID const&, unsigned char, LLViewerRegion*)+0x193) [0x960ab0d]
1918: ELF(LLViewerObjectList::createObject(unsigned char, LLViewerRegion*, LLUUID const&, unsigned int, LLHost const&)+0x8f) [0x961c9f3]
2019: ELF(LLViewerObjectList::processObjectUpdate(LLMessageSystem*, void**, e_object_update_type, bool, bool)+0x8d1) [0x961e83d]
2120: ELF(process_object_update(LLMessageSystem*, void**)+0x9d) [0x95ccc9e]
2221: ELF(LLMessageTemplate::callHandlerFunc(LLMessageSystem*) const+0x47) [0x9af995d]
2322: ELF(LLTemplateMessageReader::decodeData(unsigned char const*, LLHost const&)+0xcc8) [0x9b2d12c]
2423: ELF(LLTemplateMessageReader::readMessage(unsigned char const*, LLHost const&)+0x1f) [0x9b2d653]
2524: ELF(LLMessageSystem::checkMessages(long long)+0x1211) [0x9af0205]
2625: ELF(LLMessageSystem::checkAllMessages(long long, LLPumpIO*)+0x2b) [0x9af057d]
2726: ELF(LLAppViewer::idleNetwork()+0x2ab) [0x8519b85]
2827: ELF(LLAppViewer::idle()+0xd5c) [0x85355fe]
2928: ELF(LLAppViewer::mainLoop()+0x7fe) [0x8536cdc]
3029: ELF(main+0x213) [0x996433c]
3130: /lib/i686/cmov/libc.so.6(__libc_start_main+0xe5) [0xb5f45775]
3231: bin/do-not-directly-run-imprudence-bin [0x846f7e1]