diff options
author | Aimee Linden <aimee@lindenlab.com> | 2010-05-24 02:27:07 +0100 |
---|---|---|
committer | Aimee Linden <aimee@lindenlab.com> | 2010-05-24 02:27:07 +0100 |
commit | 15c3b2c6309fa4b45376f3d62e33bfcd3ccdbfc7 (patch) | |
tree | 83ed71b33c61f122f755eeb081dca6e37833516d /indra/newview | |
parent | 12171ddba3c70b73e53bf103a45779262b38c6ec (diff) |
EXT-7335 WIP Added notification of expiring voice effects
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
-rw-r--r-- | indra/newview/llfloaternotificationsconsole.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llfloatervoiceeffect.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llfloatervoiceeffect.h | 2 | ||||
-rw-r--r-- | indra/newview/llpanelvoiceeffect.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanelvoiceeffect.h | 2 | ||||
-rw-r--r-- | indra/newview/llvoiceclient.h | 2 | ||||
-rw-r--r-- | indra/newview/llvoicevivox.cpp | 187 | ||||
-rw-r--r-- | indra/newview/llvoicevivox.h | 13 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 33 |
10 files changed, 232 insertions, 26 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dd5774929e..cb9177587f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10606,6 +10606,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>VoiceEffectExpiryWarningTime</key> + <map> + <key>Comment</key> + <string>How much notice to give of voice effect subscriptions expiry, in seconds.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>259200.0</real> + </map> <key>AutoDisengageMic</key> <map> <key>Comment</key> diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index b744bff084..105d7f9201 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -184,7 +184,7 @@ BOOL LLFloaterNotificationConsole::postBuild() addChannel("Ignore"); addChannel("Visible", true); // all the ones below attach to the Visible channel - addChannel("History"); + addChannel("Persistent"); addChannel("Alerts"); addChannel("AlertModal"); addChannel("Group Notifications"); diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp index e30a50fab7..f31ab96985 100644 --- a/indra/newview/llfloatervoiceeffect.cpp +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -230,9 +230,9 @@ void LLFloaterVoiceEffect::updateControls() } // virtual -void LLFloaterVoiceEffect::onVoiceEffectChanged(bool new_effects) +void LLFloaterVoiceEffect::onVoiceEffectChanged(bool effect_list_updated) { - if (new_effects) + if (effect_list_updated) { refreshEffectList(); } diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h index ed38cd6925..46b241bd17 100644 --- a/indra/newview/llfloatervoiceeffect.h +++ b/indra/newview/llfloatervoiceeffect.h @@ -57,7 +57,7 @@ private: void updateControls(); /// Called by voice effect provider when voice effect list is changed. - virtual void onVoiceEffectChanged(bool new_effects); + virtual void onVoiceEffectChanged(bool effect_list_updated); void onClickRecord(); void onClickPlay(); diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index 140feb7a54..4f73f38edc 100644 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -110,7 +110,7 @@ void LLPanelVoiceEffect::onCommitVoiceEffect() } // virtual -void LLPanelVoiceEffect::onVoiceEffectChanged(bool new_effects) +void LLPanelVoiceEffect::onVoiceEffectChanged(bool effect_list_updated) { update(); } diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h index 008123a4e4..bd7bdd04f2 100644 --- a/indra/newview/llpanelvoiceeffect.h +++ b/indra/newview/llpanelvoiceeffect.h @@ -56,7 +56,7 @@ private: void update(); /// Called by voice effect provider when voice effect list is changed. - virtual void onVoiceEffectChanged(bool new_effects); + virtual void onVoiceEffectChanged(bool effect_list_updated); // Fixed entries in the voice effect list typedef enum e_voice_effect_combo_items diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 7f8f979da0..744ec84023 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -266,7 +266,7 @@ class LLVoiceEffectObserver { public: virtual ~LLVoiceEffectObserver() { } - virtual void onVoiceEffectChanged(bool new_effects) = 0; + virtual void onVoiceEffectChanged(bool effect_list_updated) = 0; }; typedef std::multimap<const std::string, const LLUUID, LLDictionaryLess> voice_effect_list_t; diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 304321b361..d786b4d928 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -60,6 +60,7 @@ #include "llviewerparcelmgr.h" //#include "llfirstuse.h" #include "llspeakers.h" +#include "lltrans.h" #include "llviewerwindow.h" #include "llviewercamera.h" @@ -96,6 +97,9 @@ const int MAX_LOGIN_RETRIES = 12; // blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability. const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50; +// How often to check for expired voice fonts +const F32 VOICE_FONT_EXPIRY_INTERVAL = 1.f; + // Maximum length of capture buffer recordings const F32 CAPTURE_BUFFER_MAX_TIME = 15.f; @@ -781,7 +785,7 @@ void LLVivoxVoiceClient::stateMachine() closeSocket(); deleteAllSessions(); deleteAllBuddies(); - deleteVoiceFonts(); + deleteAllVoiceFonts(); deleteVoiceFontTemplates(); mConnectorHandle.clear(); @@ -1372,6 +1376,10 @@ void LLVivoxVoiceClient::stateMachine() //MARK: stateVoiceFontsReceived case stateVoiceFontsReceived: // Voice font list received + // Set up the timer to check for expiring voice fonts + mVoiceFontExpiryTimer.start(); + mVoiceFontExpiryTimer.setTimerExpirySec(VOICE_FONT_EXPIRY_INTERVAL); + #if USE_SESSION_GROUPS // create the main session group setState(stateCreatingSessionGroup); @@ -1600,6 +1608,13 @@ void LLVivoxVoiceClient::stateMachine() enforceTether(); } + // Do notifications for expiring Voice Fonts. + if (mVoiceFontExpiryTimer.hasExpired()) + { + expireVoiceFonts(); + mVoiceFontExpiryTimer.setTimerExpirySec(VOICE_FONT_EXPIRY_INTERVAL); + } + // Send an update only if the ptt or mute state has changed (which shouldn't be able to happen that often // -- the user can only click so fast) or every 10hz, whichever is sooner. // Sending for every volume update causes an excessive flood of messages whenever a volume slider is dragged. @@ -1669,7 +1684,7 @@ void LLVivoxVoiceClient::stateMachine() mAccountHandle.clear(); deleteAllSessions(); deleteAllBuddies(); - deleteVoiceFonts(); + deleteAllVoiceFonts(); deleteVoiceFontTemplates(); if(mVoiceEnabled && !mRelogRequested) @@ -6461,7 +6476,6 @@ LLSD LLVivoxVoiceClient::getVoiceEffectProperties(const LLUUID& id) voiceFontEntry *font = iter->second; sd["name"] = font->mName; - sd["expired"] = font->mHasExpired; sd["expiry_date"] = font->mExpirationDate; sd["is_new"] = font->mIsNew; @@ -6471,7 +6485,6 @@ LLSD LLVivoxVoiceClient::getVoiceEffectProperties(const LLUUID& id) LLVivoxVoiceClient::voiceFontEntry::voiceFontEntry(LLUUID& id) : mID(id), mFontIndex(0), - mHasExpired(false), mFontType(VOICE_FONT_TYPE_NONE), mFontStatus(VOICE_FONT_STATUS_NONE), mIsNew(false) @@ -6487,7 +6500,7 @@ void LLVivoxVoiceClient::refreshVoiceEffectLists(bool clear_lists) if (clear_lists) { mVoiceFontsReceived = false; - deleteVoiceFonts(); + deleteAllVoiceFonts(); deleteVoiceFontTemplates(); } @@ -6533,12 +6546,23 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, voice_font_map_t& font_map = template_font ? mVoiceFontTemplateMap : mVoiceFontMap; voice_effect_list_t& font_list = template_font ? mVoiceFontTemplateList : mVoiceFontList; - // Check whether we've seen this font before and create an entry for it if not. + // Check whether we've seen this font before. voice_font_map_t::iterator iter = font_map.find(font_id); bool new_font = (iter == font_map.end()); + + // If it is a new (unexpired) font create a new entry, otherwise update the existing one. if (new_font) { - font = new voiceFontEntry(font_id); + if (!has_expired) + { + font = new voiceFontEntry(font_id); + } + else + { + LL_DEBUGS("Voice") << (template_font?"Template: ":"") << font_id + << " (" << font_index << ") : " << name << " has expired." << LL_ENDL; + } + } else { @@ -6547,15 +6571,47 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, if (font) { + // Remove fonts that have expired since we last saw them. + if (has_expired) + { + LL_DEBUGS("Voice") << (template_font?"Template: ":"") << font_id + << " (" << font_index << ") : " << name << " has expired, removing." + << LL_ENDL; + + deleteVoiceFont(font_id); + return; + } + font->mFontIndex = font_index; // Use the description for the human readable name if available, as the // "name" may be a UUID. font->mName = description.empty() ? name : description; font->mExpirationDate = expiration_date; - font->mHasExpired = has_expired; font->mFontType = font_type; font->mFontStatus = font_status; + F64 expiry_time = 0.f; + + // Set the expiry timer to trigger a notification when the voice font can no longer be used. + font->mExpiryTimer.start(); + expiry_time = expiration_date.secondsSinceEpoch() - LLTimer::getTotalSeconds(); + font->mExpiryTimer.setTimerExpirySec(expiry_time); + + // Set the warning timer to some interval before actual expiry. + F64 warning_time = (F64)gSavedSettings.getF32("VoiceEffectExpiryWarningTime"); + if (warning_time > 0.f) + { + font->mExpiryWarningTimer.start(); + expiry_time = (expiration_date.secondsSinceEpoch() - warning_time) + - LLTimer::getTotalSeconds(); + font->mExpiryWarningTimer.setTimerExpirySec(expiry_time); + } + else + { + // Disable the warning timer. + font->mExpiryWarningTimer.stop(); + } + // Only flag it as a new font if we have already seen the font list. if (!template_font && mVoiceFontsReceived && new_font) { @@ -6563,9 +6619,16 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, mVoiceFontsNew = true; } + if (new_font) + { + font_map.insert(voice_font_map_t::value_type(font->mID, font)); + font_list.insert(voice_effect_list_t::value_type(font->mName, font->mID)); + } + + // Debugging stuff + LL_DEBUGS("Voice") << (template_font?"Template: ":"") << font_id - << " (" << font_index << ") : " << name << (has_expired?" (Expired)":"") - << LL_ENDL; + << " (" << font_index << ") : " << name << LL_ENDL; if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN) { @@ -6575,16 +6638,108 @@ void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, { LL_DEBUGS("Voice") << "Unknown voice font status: " << font_status << LL_ENDL; } + } +} - if (new_font) +void LLVivoxVoiceClient::expireVoiceFonts() +{ + // *TODO: If we are selling voice fonts in packs, there are probably + // going to be a number of fonts with the same expiration time, so would + // be more efficient to just keep a list of expiration times rather + // than checking each font individually. + + bool have_expired = false; + bool will_expire = false; + bool expired_in_use = false; + + LLUUID current_effect = LLVoiceClient::instance().getVoiceEffectDefault(); + + voice_font_map_t::iterator iter; + for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter) + { + voiceFontEntry* voice_font = iter->second; + LLTimer& expiry_timer = voice_font->mExpiryTimer; + LLTimer& warning_timer = voice_font->mExpiryWarningTimer; + + // Check for expired voice fonts + if (expiry_timer.getStarted() && expiry_timer.hasExpired()) { - font_map.insert(voice_font_map_t::value_type(font->mID, font)); - font_list.insert(voice_effect_list_t::value_type(font->mName, font->mID)); + // Check whether it is the active voice font + if (voice_font->mID == current_effect) + { + // Reset to no voice effect. + setVoiceEffect(LLUUID::null); + expired_in_use = true; + } + deleteVoiceFont(voice_font->mID); + have_expired = true; + } + + // Check for voice fonts that will expire in less that the warning time + if (warning_timer.getStarted() && warning_timer.hasExpired()) + { + will_expire = true; + warning_timer.stop(); + } + } + + LLSD args; + args["URL"] = LLTrans::getString("voice_morphing_url"); + + // Give a notification if any voice fonts have expired. + if (have_expired) + { + if (expired_in_use) + { + LLNotificationsUtil::add("VoiceEffectsExpiredInUse", args); + } + else + { + LLNotificationsUtil::add("VoiceEffectsExpired", args); + } + + // Refresh voice font lists in the UI. + notifyVoiceFontObservers(true); + } + + // Give a warning notification if any voice fonts are due to expire. + if (will_expire) + { + S32 seconds = gSavedSettings.getF32("VoiceEffectExpiryWarningTime"); + args["INTERVAL"] = llformat("%d", (seconds / SEC_PER_DAY)); + + LLNotificationsUtil::add("VoiceEffectsWillExpire", args); + } +} + +void LLVivoxVoiceClient::deleteVoiceFont(const LLUUID& id) +{ + // Remove the entry from the voice font list. + voice_effect_list_t::iterator list_iter = mVoiceFontList.begin(); + while (list_iter != mVoiceFontList.end()) + { + if (list_iter->second == id) + { + mVoiceFontList.erase(list_iter++); + } + else + { + ++list_iter; } } + + // Find the entry in the voice font map and erase its data. + voice_font_map_t::iterator map_iter = mVoiceFontMap.find(id); + if (map_iter != mVoiceFontMap.end()) + { + delete map_iter->second; + } + + // Remove the entry from the voice font map. + mVoiceFontMap.erase(map_iter); } -void LLVivoxVoiceClient::deleteVoiceFonts() +void LLVivoxVoiceClient::deleteAllVoiceFonts() { mVoiceFontList.clear(); @@ -6723,14 +6878,14 @@ void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer) mVoiceFontObservers.erase(observer); } -void LLVivoxVoiceClient::notifyVoiceFontObservers(bool new_fonts) +void LLVivoxVoiceClient::notifyVoiceFontObservers(bool lists_changed) { for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); it != mVoiceFontObservers.end(); ) { LLVoiceEffectObserver* observer = *it; - observer->onVoiceEffectChanged(new_fonts); + observer->onVoiceEffectChanged(lists_changed); // In case onVoiceEffectChanged() deleted an entry. it = mVoiceFontObservers.upper_bound(observer); } diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 130fdac146..d71fe132c5 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -857,7 +857,9 @@ private: // Voice Fonts - void deleteVoiceFonts(); + void expireVoiceFonts(); + void deleteVoiceFont(const LLUUID& id); + void deleteAllVoiceFonts(); void deleteVoiceFontTemplates(); S32 getVoiceFontIndex(const LLUUID& id) const; @@ -867,7 +869,7 @@ private: void accountGetTemplateFontsSendMessage(); void sessionSetVoiceFontSendMessage(sessionState *session); - void notifyVoiceFontObservers(bool new_fonts = false); + void notifyVoiceFontObservers(bool lists_changed = false); typedef enum e_voice_font_type { @@ -894,10 +896,12 @@ private: S32 mFontIndex; std::string mName; LLDate mExpirationDate; - bool mHasExpired; S32 mFontType; S32 mFontStatus; bool mIsNew; + + LLTimer mExpiryTimer; + LLTimer mExpiryWarningTimer; }; bool mVoiceFontsReceived; @@ -912,6 +916,9 @@ private: typedef std::set<LLVoiceEffectObserver*> voice_font_observer_set_t; voice_font_observer_set_t mVoiceFontObservers; + LLTimer mVoiceFontExpiryTimer; + + // Audio capture buffer void captureBufferRecordStartSendMessage(); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 999f804e71..6b5659f6c0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5957,6 +5957,39 @@ We are creating a voice channel for you. This may take up to one minute. </notification> <notification + icon="notify.tga" + name="VoiceEffectsExpired" + sound="UISndAlert" + persist="true" + type="notify"> +Subscribed Voice Effects have expired. +[[URL] Renew your subscription] to reactivate them. + <unique/> + </notification> + + <notification + icon="notify.tga" + name="VoiceEffectsExpiredInUse" + sound="UISndAlert" + persist="true" + type="notify"> +The active Voice Effect has expired, your normal voice settings have been applied. +[[URL] Renew your subscription] to reactivate it. + <unique/> + </notification> + + <notification + icon="notify.tga" + name="VoiceEffectsWillExpire" + sound="UISndAlert" + persist="true" + type="notify"> +Voice Effects will expire in less than [INTERVAL] days. +[[URL] Renew your subscription] or they will be removed. + <unique/> + </notification> + + <notification icon="notifytip.tga" name="Cannot enter parcel: not a group member" type="notifytip"> |