/** * @file llfloatervoicewizard.cpp * @author Richard Nelson * @brief Voice communication set-up wizard * * Copyright (c) 2007-2007, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. */ #include "llviewerprecompiledheaders.h" #include "llfloatervoicewizard.h" #include "llagent.h" #include "llbutton.h" #include "llcombobox.h" #include "llfocusmgr.h" #include "lliconctrl.h" #include "llprefsvoice.h" #include "llsliderctrl.h" #include "llviewercontrol.h" #include "llvieweruictrlfactory.h" #include "llvoiceclient.h" #include "llimpanel.h" LLFloaterVoiceWizard::LLFloaterVoiceWizard(const LLSD& seed) : LLFloater("floater_voice_wizard"), mDevicePanel(NULL) { mFactoryMap["device_settings"] = LLCallbackMap(createPanelDeviceSettings, this); // do not automatically open singleton floaters (as result of getInstance()) BOOL no_open = FALSE; gUICtrlFactory->buildFloater(this, "floater_voice_wizard.xml", &mFactoryMap, no_open); mLogic = new LLPrefsVoiceLogic(this); center(); } LLFloaterVoiceWizard::~LLFloaterVoiceWizard() { delete mLogic; mLogic = NULL; } BOOL LLFloaterVoiceWizard::postBuild() { childSetAction("next_btn", onClickNext, this); childSetAction("back_btn", onClickBack, this); childSetAction("ok_btn", onClickOK, this); childSetAction("cancel_btn", onClickCancel, this); childSetCommitCallback("voice_enable", onCommitVoiceEnable, this); return TRUE; } void LLFloaterVoiceWizard::draw() { mLogic->refresh(); if (mDevicePanel) { mDevicePanel->refresh(); } LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName(this, "wizard_tabs"); if (tabs) { // if on first tab, disable back button, etc if (tabs->getCurrentPanelIndex() == 0) { if (gSavedSettings.getBOOL("EnableVoiceChat")) { childSetEnabled("next_btn", TRUE); setDefaultBtn(gUICtrlFactory->getButtonByName(this, "next_btn")); } else { childSetEnabled("next_btn", FALSE); setDefaultBtn(gUICtrlFactory->getButtonByName(this, "ok_btn")); } childSetEnabled("back_btn", FALSE); } else { // if on any tab but the last, enable the next button if (tabs->getCurrentPanelIndex() < tabs->getTabCount() - 1) { childSetEnabled("next_btn", TRUE); setDefaultBtn(gUICtrlFactory->getButtonByName(this, "next_btn")); } else { childSetEnabled("next_btn", FALSE); setDefaultBtn(gUICtrlFactory->getButtonByName(this, "ok_btn")); } childSetEnabled("back_btn", TRUE); } } // because we can simultaneously change voice settings from the preferences UI // we need to stay in sync childSetValue("voice_enable", gSavedSettings.getBOOL("EnableVoiceChat") ? "1" : "0"); // show appropriate text on first tab childSetVisible("voice_intro_text3", !gSavedSettings.getBOOL("EnableVoiceChat")); childSetVisible("voice_intro_text4", gSavedSettings.getBOOL("EnableVoiceChat")); LLFloater::draw(); } void LLFloaterVoiceWizard::onOpen() { if(mDevicePanel) { mDevicePanel->onOpen(); } LLFloater::onOpen(); } void LLFloaterVoiceWizard::onClose(bool app_quitting) { if(mDevicePanel) { mDevicePanel->onClose(app_quitting); } LLFloater::onClose(app_quitting); } // static void LLFloaterVoiceWizard::onClickNext(void *user_data) { LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName((LLFloater*)user_data, "wizard_tabs"); if (tabs) { tabs->selectNextTab(); } } // static void LLFloaterVoiceWizard::onClickBack(void *user_data) { LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName((LLFloater*)user_data, "wizard_tabs"); if (tabs) { tabs->selectPrevTab(); } } // static void LLFloaterVoiceWizard::onClickOK(void *user_data) { LLFloaterVoiceWizard* self = (LLFloaterVoiceWizard*)user_data; // propagate tuning mic volume to actual mic volume self->mLogic->apply(); if (self->mDevicePanel) { self->mDevicePanel->apply(); } self->close(); } // static void LLFloaterVoiceWizard::onClickCancel(void *user_data) { LLFloaterVoiceWizard* self = (LLFloaterVoiceWizard*)user_data; self->mLogic->cancel(); if (self->mDevicePanel) { self->mDevicePanel->cancel(); } self->close(); } // static void LLFloaterVoiceWizard::onCommitVoiceEnable(LLUICtrl* ctrl, void* user_data) { gSavedSettings.setBOOL("EnableVoiceChat", ctrl->getValue().asInteger()); } // static void* LLFloaterVoiceWizard::createPanelDeviceSettings(void* user_data) { LLFloaterVoiceWizard* floaterp = (LLFloaterVoiceWizard*)user_data; floaterp->mDevicePanel = new LLPanelDeviceSettings(); return floaterp->mDevicePanel; } // // LLPanelDeviceSettings // LLPanelDeviceSettings::LLPanelDeviceSettings() { mCtrlInputDevices = NULL; mCtrlOutputDevices = NULL; mInputDevice = gSavedSettings.getString("VoiceInputAudioDevice"); mOutputDevice = gSavedSettings.getString("VoiceOutputAudioDevice"); mDevicesUpdated = FALSE; // grab "live" mic volume level mMicVolume = gSavedSettings.getF32("AudioLevelMic"); // ask for new device enumeration // now do this in onOpen() instead... //gVoiceClient->refreshDeviceLists(); } LLPanelDeviceSettings::~LLPanelDeviceSettings() { } BOOL LLPanelDeviceSettings::postBuild() { LLSlider* volume_slider = gUICtrlFactory->getSliderBarByName(this, "mic_volume_slider"); if (volume_slider) { // set mic volume tuning slider based on last mic volume setting volume_slider->setValue(mMicVolume); } return TRUE; } void LLPanelDeviceSettings::draw() { // let user know that volume indicator is not yet available childSetVisible("wait_text", !gVoiceClient->inTuningMode()); LLPanel::draw(); F32 voice_power = gVoiceClient->tuningGetEnergy(); S32 discrete_power = 0; if (!gVoiceClient->inTuningMode()) { discrete_power = 0; } else { discrete_power = llmin(4, llfloor((voice_power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 4.f)); } if (gVoiceClient->inTuningMode()) { const S32 GAP = 5; S32 cur_x = 100; S32 cur_y = 15; for(S32 power_bar_idx = 0; power_bar_idx < 5; power_bar_idx++) { if (power_bar_idx < discrete_power) { LLColor4 color = (power_bar_idx >= 3) ? gSavedSettings.getColor4("OverdrivenColor") : gSavedSettings.getColor4("SpeakingColor"); gl_rect_2d(cur_x, cur_y + 20, cur_x + 20, cur_y, color, TRUE); } gl_rect_2d(cur_x, cur_y + 20, cur_x + 20, cur_y, LLColor4::grey, FALSE); cur_x += 20 + GAP; } } } void LLPanelDeviceSettings::apply() { std::string s; if(mCtrlInputDevices) { s = mCtrlInputDevices->getSimple(); gSavedSettings.setString("VoiceInputAudioDevice", s); } if(mCtrlOutputDevices) { s = mCtrlOutputDevices->getSimple(); gSavedSettings.setString("VoiceOutputAudioDevice", s); } // assume we are being destroyed by closing our embedding window gSavedSettings.setF32("AudioLevelMic", mMicVolume); } void LLPanelDeviceSettings::cancel() { gSavedSettings.setString("VoiceInputAudioDevice", mInputDevice); gSavedSettings.setString("VoiceOutputAudioDevice", mOutputDevice); if(mCtrlInputDevices) mCtrlInputDevices->setSimple(mInputDevice); if(mCtrlOutputDevices) mCtrlOutputDevices->setSimple(mOutputDevice); } void LLPanelDeviceSettings::refresh() { //grab current volume LLSlider* volume_slider = gUICtrlFactory->getSliderBarByName(this, "mic_volume_slider"); if (volume_slider) { // set mic volume tuning slider based on last mic volume setting mMicVolume = (F32)volume_slider->getValue().asReal(); gVoiceClient->tuningSetMicVolume(mMicVolume); } // Fill in popup menus mCtrlInputDevices = LLUICtrlFactory::getComboBoxByName(this, "voice_input_device"); mCtrlOutputDevices = LLUICtrlFactory::getComboBoxByName(this, "voice_output_device"); if(!gVoiceClient->deviceSettingsAvailable()) { // The combo boxes are disabled, since we can't get the device settings from the daemon just now. // Put the currently set default (ONLY) in the box, and select it. if(mCtrlInputDevices) { mCtrlInputDevices->removeall(); mCtrlInputDevices->add( mInputDevice, ADD_BOTTOM ); mCtrlInputDevices->setSimple(mInputDevice); } if(mCtrlOutputDevices) { mCtrlOutputDevices->removeall(); mCtrlOutputDevices->add( mOutputDevice, ADD_BOTTOM ); mCtrlOutputDevices->setSimple(mOutputDevice); } } else if (!mDevicesUpdated) { LLVoiceClient::deviceList *devices; LLVoiceClient::deviceList::iterator iter; if(mCtrlInputDevices) { mCtrlInputDevices->removeall(); mCtrlInputDevices->add( "Default", ADD_BOTTOM ); devices = gVoiceClient->getCaptureDevices(); for(iter=devices->begin(); iter != devices->end(); iter++) { mCtrlInputDevices->add( *iter, ADD_BOTTOM ); } if(!mCtrlInputDevices->setSimple(mInputDevice)) { mCtrlInputDevices->setSimple("Default"); } } if(mCtrlOutputDevices) { mCtrlOutputDevices->removeall(); mCtrlOutputDevices->add( "Default", ADD_BOTTOM ); devices = gVoiceClient->getRenderDevices(); for(iter=devices->begin(); iter != devices->end(); iter++) { mCtrlOutputDevices->add( *iter, ADD_BOTTOM ); } if(!mCtrlOutputDevices->setSimple(mOutputDevice)) { mCtrlOutputDevices->setSimple("Default"); } } mDevicesUpdated = TRUE; } } void LLPanelDeviceSettings::onOpen() { mDevicesUpdated = FALSE; // ask for new device enumeration gVoiceClient->refreshDeviceLists(); // put voice client in "tuning" mode gVoiceClient->tuningStart(); } void LLPanelDeviceSettings::onClose(bool app_quitting) { gVoiceClient->tuningStop(); } // // LLFloaterDeviceSettings // LLFloaterDeviceSettings::LLFloaterDeviceSettings(const LLSD& seed) : LLFloater("floater_device_settings"), mDevicePanel(NULL) { mFactoryMap["device_settings"] = LLCallbackMap(createPanelDeviceSettings, this); // do not automatically open singleton floaters (as result of getInstance()) BOOL no_open = FALSE; gUICtrlFactory->buildFloater(this, "floater_device_settings.xml", &mFactoryMap, no_open); center(); } void LLFloaterDeviceSettings::onOpen() { if(mDevicePanel) { mDevicePanel->onOpen(); } LLFloater::onOpen(); } void LLFloaterDeviceSettings::onClose(bool app_quitting) { if(mDevicePanel) { mDevicePanel->onClose(app_quitting); } setVisible(FALSE); } void LLFloaterDeviceSettings::apply() { if (mDevicePanel) { mDevicePanel->apply(); } } void LLFloaterDeviceSettings::cancel() { if (mDevicePanel) { mDevicePanel->cancel(); } } void LLFloaterDeviceSettings::draw() { if (mDevicePanel) { mDevicePanel->refresh(); } LLFloater::draw(); } // static void* LLFloaterDeviceSettings::createPanelDeviceSettings(void* user_data) { LLFloaterDeviceSettings* floaterp = (LLFloaterDeviceSettings*)user_data; floaterp->mDevicePanel = new LLPanelDeviceSettings(); return floaterp->mDevicePanel; }