diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index e78dd3baf8..4df2808b3d 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -37,6 +37,7 @@ set(cmake_SOURCE_FILES
FreeType.cmake
GStreamer010Plugin.cmake
GooglePerfTools.cmake
+ Growl.cmake
JPEG.cmake
LLAddBuildTest.cmake
LLAudio.cmake
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index e852cf463c..bea43f9308 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -38,6 +38,8 @@ if(WINDOWS)
libapr-1.dll
libaprutil-1.dll
libapriconv-1.dll
+ lgggrowl++.dll
+ lgggrowl.dll
)
# *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
@@ -48,6 +50,8 @@ if(WINDOWS)
libapr-1.dll
libaprutil-1.dll
libapriconv-1.dll
+ lgggrowl++.dll
+ lgggrowl.dll
)
if(USE_GOOGLE_PERFTOOLS)
@@ -169,6 +173,7 @@ elseif(DARWIN)
libllqtwebkit.dylib
libndofdev.dylib
libexception_handler.dylib
+ libgrowl.dylib
)
# fmod is statically linked on darwin
@@ -236,6 +241,7 @@ elseif(LINUX)
libtcmalloc.so
libuuid.so.1
libssl.so.0.9.7
+ libnotify.so
)
if (FMOD)
diff --git a/indra/cmake/FindLibnotify.cmake b/indra/cmake/FindLibnotify.cmake
new file mode 100644
index 0000000000..395dac804e
--- /dev/null
+++ b/indra/cmake/FindLibnotify.cmake
@@ -0,0 +1,46 @@
+# -*- cmake -*-
+
+# - Find libnotify
+# Find the libnotify includes and library
+# This module defines
+# LIBNOTIFY_INCLUDE_DIR, where to find notify.h, etc.
+# LIBNOTIFY_LIBRARIES, the libraries needed to use libnotify.
+# LIBNOTIFY_FOUND, If false, do not try to use libnotify.
+# also defined, but not for general use are
+# LIBNOTIFY_LIBRARY, where to find the libnotify library.
+
+FIND_PATH(LIBNOTIFY_INCLUDE_DIR notify.h
+ PATH_SUFFIXES libnotify
+ )
+
+SET(LIBNOTIFY_NAMES ${LIBNOTIFY_NAMES} notify)
+FIND_LIBRARY(LIBNOTIFY_LIBRARY
+ NAMES ${LIBNOTIFY_NAMES}
+ )
+
+IF (LIBNOTIFY_LIBRARY AND LIBNOTIFY_INCLUDE_DIR)
+ SET(LIBNOTIFY_LIBRARIES ${LIBNOTIFY_LIBRARY})
+ SET(LIBNOTIFY_FOUND "YES")
+ELSE (LIBNOTIFY_LIBRARY AND LIBNOTIFY_INCLUDE_DIR)
+ SET(LIBNOTIFY_FOUND "NO")
+ENDIF (LIBNOTIFY_LIBRARY AND LIBNOTIFY_INCLUDE_DIR)
+
+
+IF (LIBNOTIFY_FOUND)
+ IF (NOT LIBNOTIFY_FIND_QUIETLY)
+ MESSAGE(STATUS "Found libnotify: '${LIBNOTIFY_LIBRARIES}' and header in '${LIBNOTIFY_INCLUDE_DIR}'")
+ ENDIF (NOT LIBNOTIFY_FIND_QUIETLY)
+ELSE (LIBNOTIFY_FOUND)
+ IF (LIBNOTIFY_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find libnotify library")
+ ENDIF (LIBNOTIFY_FIND_REQUIRED)
+ENDIF (LIBNOTIFY_FOUND)
+
+# Deprecated declarations.
+SET (NATIVE_LIBNOTIFY_INCLUDE_PATH ${LIBNOTIFY_INCLUDE_DIR} )
+GET_FILENAME_COMPONENT (NATIVE_LIBNOTIFY_LIB_PATH ${LIBNOTIFY_LIBRARY} PATH)
+
+MARK_AS_ADVANCED(
+ LIBNOTIFY_LIBRARY
+ LIBNOTIFY_INCLUDE_DIR
+ )
diff --git a/indra/cmake/Growl.cmake b/indra/cmake/Growl.cmake
new file mode 100644
index 0000000000..7b2c9177d9
--- /dev/null
+++ b/indra/cmake/Growl.cmake
@@ -0,0 +1,23 @@
+# -*- cmake -*-
+
+# Growl is actually libnotify on linux systems.
+if (STANDALONE)
+ set(LIBNOTIFY_FIND_REQUIRED ON)
+ include(FindLibnotify)
+ set(GROWL_INCLUDE_DIRS ${LIBNOTIFY_INCLUDE_DIR})
+ set(GROWL_LIBRARY ${LIBNOTIFY_LIBRARIES})
+else (STANDALONE)
+ include(Prebuilt)
+ use_prebuilt_binary(Growl)
+ if (DARWIN)
+ set(GROWL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/Growl)
+ set(GROWL_LIBRARY growl)
+ elseif (WINDOWS)
+ set(GROWL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/Growl)
+ set(GROWL_LIBRARY lgggrowl++)
+ elseif (LINUX)
+ # Everything glib-2.0 and GTK-specific is pulled in by UI.cmake.. Ugh.
+ set(GROWL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/libnotify)
+ set(GROWL_LIBRARY notify)
+ endif (DARWIN)
+endif (STANDALONE)
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c707e4b0a3..f7076d8ed3 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -41,6 +41,7 @@ include(LLKDU)
include(ViewerMiscLibs)
include(LLLogin)
include(CMakeCopyIfDifferent)
+include(Growl)
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
@@ -65,12 +66,15 @@ include_directories(
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
${LLLOGIN_INCLUDE_DIRS}
${UPDATER_INCLUDE_DIRS}
+ ${GROWL_INCLUDE_DIRS}
)
set(viewer_SOURCE_FILES
chatbar_as_cmdline.cpp
kcwlinterface.cpp
fscontactsfloater.cpp
+ growlmanager.cpp
+ growlnotifier.cpp
llagent.cpp
llagentaccess.cpp
llagentcamera.cpp
@@ -616,6 +620,8 @@ set(viewer_HEADER_FILES
chatbar_as_cmdline.h
kcwlinterface.h
fscontactsfloater.h
+ growlmanager.h
+ growlnotifier.h
llagent.h
llagentaccess.h
llagentcamera.h
@@ -1144,6 +1150,11 @@ source_group("CMake Rules" FILES ViewerInstall.cmake)
if (DARWIN)
LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp)
+ LIST(APPEND viewer_HEADER_FILES growlnotifiermacosx-objc.h)
+ LIST(APPEND viewer_SOURCE_FILES growlnotifiermacosx-objc.mm)
+ LIST(APPEND viewer_SOURCE_FILES growlnotifiermacosx.h)
+ LIST(APPEND viewer_SOURCE_FILES growlnotifiermacosx.cpp)
+
find_library(AGL_LIBRARY AGL)
find_library(APPKIT_LIBRARY AppKit)
@@ -1185,6 +1196,8 @@ endif (DARWIN)
if (LINUX)
LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp)
LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
+ LIST(APPEND viewer_HEADER_FILES desktopnotifierlinux.h)
+ LIST(APPEND viewer_SOURCE_FILES desktopnotifierlinux.cpp)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
set(viewer_LIBRARIES
@@ -1194,11 +1207,13 @@ endif (LINUX)
if (WINDOWS)
list(APPEND viewer_SOURCE_FILES
+ growlnotifierwin.cpp
llappviewerwin32.cpp
llwindebug.cpp
)
list(APPEND viewer_HEADER_FILES
+ growlnotifierwin.h
llappviewerwin32.h
llwindebug.h
)
@@ -1566,6 +1581,7 @@ if (WINDOWS)
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/lgggrowl.dll
SLPlugin
media_plugin_quicktime
media_plugin_webkit
@@ -1718,6 +1734,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${CRYPTO_LIBRARIES}
${LLLOGIN_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
+ ${GROWL_LIBRARY}
)
if (LINUX OR FIRECYG OR DARWIN)
diff --git a/indra/newview/app_settings/growl_notifications.xml b/indra/newview/app_settings/growl_notifications.xml
new file mode 100644
index 0000000000..276fae7971
--- /dev/null
+++ b/indra/newview/app_settings/growl_notifications.xml
@@ -0,0 +1,177 @@
+
+
+
+
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4ff212323b..f5afd308b7 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -13106,5 +13106,27 @@
Value
1
+ PhoenixEnableGrowl
+
+ Comment
+ Enables Growl notifications
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 1
+
+ PhoenixGrowlWhenActive
+
+ Comment
+ If Growl notifications are active, show them even when the window is active.
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 0
+
diff --git a/indra/newview/desktopnotifierlinux.cpp b/indra/newview/desktopnotifierlinux.cpp
new file mode 100644
index 0000000000..ee695c5956
--- /dev/null
+++ b/indra/newview/desktopnotifierlinux.cpp
@@ -0,0 +1,131 @@
+/* Copyright (c) 2010 Discrete Dreamscape All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Discrete Dreamscape nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DISCRETE DREAMSCAPE AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DISCRETE DREAMSCAPE OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "desktopnotifierlinux.h"
+
+#include "notify.h"
+
+const char* ICON_128 = "firestorm_icon128.png";
+const char* ICON_512 = "firestorm_icon.png";
+const gint NOTIFICATION_TIMEOUT_MS = 5000;
+
+static const char* icon_wholename;
+
+const char* Find_BMP_Resource(const char *basename)
+{
+ const int PATH_BUFFER_SIZE=1000;
+ char* path_buffer = new char[PATH_BUFFER_SIZE]; /* Flawfinder: ignore */
+
+ // Figure out where our BMP is living on the disk
+ snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s",
+ gDirUtilp->getAppRODataDir().c_str(),
+ gDirUtilp->getDirDelimiter().c_str(),
+ gDirUtilp->getDirDelimiter().c_str(),
+ basename);
+ path_buffer[PATH_BUFFER_SIZE-1] = '\0';
+
+ return path_buffer;
+}
+
+DesktopNotifierLinux::DesktopNotifierLinux()
+{
+ if (notify_init("Firestorm Viewer")) {
+ LL_INFOS("DesktopNotifierLinux") << "Linux desktop notifications initialized." << LL_ENDL;
+ // Find the name of our notification server. I kinda don't expect it to change after the start of the program.
+ gchar* name = NULL;
+ gchar* vendor = NULL;
+ gchar* version = NULL;
+ gchar* spec = NULL;
+ bool info_success = notify_get_server_info(&name, &vendor, &version, &spec);
+ if (info_success) {
+ LL_INFOS("DesktopNotifierLinux") << "Server name: " << name << LL_ENDL;
+ LL_INFOS("DesktopNotifierLinux") << "Server vendor: " << vendor << LL_ENDL;
+ LL_INFOS("DesktopNotifierLinux") << "Server version: " << version << LL_ENDL;
+ LL_INFOS("DesktopNotifierLinux") << "Server spec: " << spec << LL_ENDL;
+ }
+ if (!info_success || strncmp("notification-daemon", name, 19)) {
+ // We're likely talking to notification-daemon, and I don't feel like scaling. Use a premade 128x128 icon.
+ icon_wholename = Find_BMP_Resource(ICON_128);
+ } else {
+ // Talking to NotifyOSD or something else. Try the 512x512 icon and let it scale on its own.
+ icon_wholename = Find_BMP_Resource(ICON_512);
+ }
+ LL_INFOS("DesktopNotifierLinux") << "Linux desktop notification icon: " << icon_wholename << LL_ENDL;
+ } else {
+ LL_WARNS("DesktopNotifierLinux") << "Linux desktop notifications FAILED to initialize." << LL_ENDL;
+ }
+}
+
+void DesktopNotifierLinux::showNotification(const std::string& notification_title, const std::string& notification_message, const std::string& notification_type)
+{
+ LL_INFOS("DesktopNotifierLinux") << "New notification title: " << notification_title << LL_ENDL;
+ LL_INFOS("DesktopNotifierLinux") << "New notification message: " << notification_message << LL_ENDL;
+ LL_INFOS("DesktopNotifierLinux") << "New notification type: " << notification_type << LL_ENDL;
+
+ static NotifyNotification* notification = notify_notification_new(
+ "Firestorm Viewer",//(gchar*)notification_title.c_str(),
+ NULL,//(gchar*)notification_message.c_str(),
+ icon_wholename,
+ NULL
+ );
+
+ notify_notification_update(
+ notification,
+ (gchar*)notification_title.c_str(),
+ (gchar*)notification_message.c_str(),
+ icon_wholename
+ );
+
+ notify_notification_set_urgency(notification, NOTIFY_URGENCY_LOW);
+ notify_notification_set_category(notification, (gchar*)notification_type.c_str());
+ notify_notification_set_timeout(notification, NOTIFICATION_TIMEOUT_MS); // NotifyOSD ignores this, sadly.
+
+ GError* error = NULL;
+ if (notify_notification_show(notification, &error)) {
+ LL_INFOS("DesktopNotifierLinux") << "Linux desktop notification type " << notification_type << "sent." << LL_ENDL;
+ } else {
+ LL_WARNS("DesktopNotifierLinux") << "Linux desktop notification FAILED to send. " << error->message << LL_ENDL;
+ }
+}
+
+bool DesktopNotifierLinux::isUsable()
+{
+ return notify_is_initted();
+}
+
+/*void DesktopNotifierLinux::registerApplication(const std::string& application, const std::set& notificationTypes)
+{
+ // Do nothing for now.
+}*/
+
+bool DesktopNotifierLinux::needsThrottle()
+{
+ return false; // NotifyOSD seems to have no issues with handling spam.. How about notification-daemon?
+}
diff --git a/indra/newview/desktopnotifierlinux.h b/indra/newview/desktopnotifierlinux.h
new file mode 100644
index 0000000000..8bd0c06f31
--- /dev/null
+++ b/indra/newview/desktopnotifierlinux.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2010 Discrete Dreamscape All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Discrete Dreamscape nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DISCRETE DREAMSCAPE AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DISCRETE DREAMSCAPE OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DESKTOPNOTIFIERLINUX_H
+#define DESKTOPNOTIFIERLINUX_H
+
+#include
+#include "growlnotifier.h"
+
+class DesktopNotifierLinux : public GrowlNotifier
+{
+ LOG_CLASS(DesktopNotifierLinux);
+public:
+ DesktopNotifierLinux();
+ ~DesktopNotifierLinux(){}
+
+ void showNotification(const std::string& notification_title, const std::string& notification_message, const std::string& notificationTypes);
+ bool isUsable();
+ //void registerApplication(const std::string& application, const std::set& notificationTypes);
+ bool needsThrottle();
+};
+
+#endif // DESKTOPNOTIFIERLINUX_H
diff --git a/indra/newview/growlmanager.cpp b/indra/newview/growlmanager.cpp
new file mode 100644
index 0000000000..209321810e
--- /dev/null
+++ b/indra/newview/growlmanager.cpp
@@ -0,0 +1,228 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldir.h"
+#include "llfile.h"
+#include "llnotifications.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llstartup.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+
+#include "growlmanager.h"
+#include "growlnotifier.h"
+#include "llwindow.h"
+#include "llfocusmgr.h"
+
+// Platform-specific includes
+#ifdef LL_DARWIN
+#include "growlnotifiermacosx.h"
+#elif LL_WINDOWS
+#include "growlnotifierwin.h"
+#elif LL_LINUX
+#include "desktopnotifierlinux.h"
+#endif
+
+
+GrowlManager *gGrowlManager = NULL;
+
+GrowlManager::GrowlManager() : LLEventTimer(GROWL_THROTTLE_CLEANUP_PERIOD)
+{
+ // Create a notifier appropriate to the platform.
+#ifdef LL_DARWIN
+ this->mNotifier = new GrowlNotifierMacOSX();
+ LL_INFOS("GrowlManagerInit") << "Created GrowlNotifierMacOSX." << LL_ENDL;
+#elif LL_WINDOWS
+ this->mNotifier = new GrowlNotifierWin();
+ LL_INFOS("GrowlManagerInit") << "Created GrowlNotifierWin." << LL_ENDL;
+#elif LL_LINUX
+ this->mNotifier = new DesktopNotifierLinux();
+ LL_INFOS("GrowlManagerInit") << "Created DesktopNotifierLinux." << LL_ENDL;
+#else
+ this->mNotifier = new GrowlNotifier();
+ LL_INFOS("GrowlManagerInit") << "Created generic GrowlNotifier." << LL_ENDL;
+#endif
+
+ // Don't do anything more if Growl isn't usable.
+ if(!mNotifier->isUsable())
+ {
+ LL_WARNS("GrowlManagerInit") << "Growl is unusable; bailing out." << LL_ENDL;
+ return;
+ }
+
+ // Hook into LLNotifications...
+ // We hook into all of them, even though (at the time of writing) nothing uses "alert", so more notifications can be added easily.
+ LLNotificationChannel::buildChannel("GrowlNotifications", "Visible", LLNotificationFilters::includeEverything);
+
+ LLNotifications::instance().getChannel("GrowlNotifications")->connectChanged(&GrowlManager::onLLNotification);
+ this->loadConfig();
+}
+
+void GrowlManager::loadConfig()
+{
+ std::string config_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "growl_notifications.xml");
+ if(config_file == "")
+ {
+ LL_WARNS("GrowlConfig") << "Couldn't find growl_notifications.xml" << LL_ENDL;
+ return;
+ }
+ LL_INFOS("GrowlConfig") << "Loading growl notification config from " << config_file << LL_ENDL;
+ llifstream configs(config_file);
+ LLSD notificationLLSD;
+ std::set notificationTypes;
+ notificationTypes.insert("Keyword Alert");
+ notificationTypes.insert("Instant Message received");
+ if(configs.is_open())
+ {
+ LLSDSerialize::fromXML(notificationLLSD, configs);
+ for(LLSD::map_iterator itr = notificationLLSD.beginMap(); itr != notificationLLSD.endMap(); ++itr)
+ {
+ GrowlNotification ntype;
+ ntype.growlName = itr->second.get("GrowlName").asString();
+ notificationTypes.insert(ntype.growlName);
+
+ if(itr->second.has("GrowlTitle"))
+ ntype.growlTitle = itr->second.get("GrowlTitle").asString();
+ if(itr->second.has("GrowlBody"))
+ ntype.growlBody = itr->second.get("GrowlBody").asString();
+ if(itr->second.has("UseDefaultTextForTitle"))
+ ntype.useDefaultTextForTitle = itr->second.get("UseDefaultTextForTitle").asBoolean();
+ else
+ ntype.useDefaultTextForTitle = false;
+ if(itr->second.has("UseDefaultTextForBody"))
+ ntype.useDefaultTextForBody = itr->second.get("UseDefaultTextForBody").asBoolean();
+ else
+ ntype.useDefaultTextForBody = false;
+ if(ntype.useDefaultTextForBody == false && ntype.useDefaultTextForTitle == false &&
+ ntype.growlBody == "" && ntype.growlTitle == "")
+ {
+ ntype.useDefaultTextForBody = true;
+ }
+ this->mNotifications[itr->first] = ntype;
+ }
+ configs.close();
+
+ this->mNotifier->registerApplication("Firestorm Viewer", notificationTypes);
+ }
+ else
+ {
+ LL_WARNS("GrowlConfig") << "Couldn't open growl config file." << LL_ENDL;
+ }
+
+}
+
+void GrowlManager::notify(const std::string& notification_title, const std::string& notification_message, const std::string& notification_type)
+{
+ static LLCachedControl enabled(gSavedSettings, "PhoenixEnableGrowl");
+ if(!enabled)
+ return;
+
+ if(!shouldNotify())
+ return;
+
+ if(this->mNotifier->needsThrottle())
+ {
+ U64 now = LLTimer::getTotalTime();
+ if(mTitleTimers.find(notification_title) != mTitleTimers.end())
+ {
+ if(mTitleTimers[notification_title] > now - GROWL_THROTTLE_TIME)
+ {
+ LL_WARNS("GrowlNotify") << "Discarded notification with title '" << notification_title << "' - spam ._." << LL_ENDL;
+ mTitleTimers[notification_title] = now;
+ return;
+ }
+ }
+ mTitleTimers[notification_title] = now;
+ }
+ this->mNotifier->showNotification(notification_title, notification_message.substr(0, GROWL_MAX_BODY_LENGTH), notification_type);
+}
+
+BOOL GrowlManager::tick()
+{
+ mTitleTimers.clear();
+ return false;
+}
+
+bool GrowlManager::onLLNotification(const LLSD& notice)
+{
+ if(notice["sigtype"].asString() != "add")
+ return false;
+ static LLCachedControl enabled(gSavedSettings, "PhoenixEnableGrowl");
+ if(!enabled)
+ return false;
+ if(!shouldNotify())
+ return false;
+ LLNotificationPtr notification = LLNotifications::instance().find(notice["id"].asUUID());
+ std::string name = notification->getName();
+ LLSD substitutions = notification->getSubstitutions();
+ if(LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ LL_WARNS("GrowlLLNotification") << "GrowlManager discarded a notification (" << name << ") - too early." << LL_ENDL;
+ return false;
+ }
+ if(gGrowlManager->mNotifications.find(name) != gGrowlManager->mNotifications.end())
+ {
+ GrowlNotification* growl_notification = &gGrowlManager->mNotifications[name];
+ std::string body = "";
+ std::string title = "";
+ if(growl_notification->useDefaultTextForTitle)
+ title = notification->getMessage();
+ else if(growl_notification->growlTitle != "")
+ {
+ LLStringUtil::format(growl_notification->growlTitle, substitutions);
+ title = growl_notification->growlTitle;
+ }
+ if(growl_notification->useDefaultTextForBody)
+ body = notification->getMessage();
+ else if(growl_notification->growlBody != "")
+ {
+ LLStringUtil::format(growl_notification->growlBody, substitutions);
+ body = growl_notification->growlBody;
+ }
+ LL_INFOS("GrowlLLNotification") << "Notice: " << title << ": " << body << LL_ENDL;
+ gGrowlManager->notify(title, body, growl_notification->growlName);
+ }
+ return false;
+}
+
+bool GrowlManager::shouldNotify()
+{
+ // This magic stolen from llappviewer.cpp. LLViewerWindow::getActive lies.
+ static LLCachedControl activated(gSavedSettings, "PhoenixGrowlWhenActive");
+ return (activated || (!gViewerWindow->mWindow->getVisible() || !gFocusMgr.getAppHasFocus()));
+}
+
+void GrowlManager::InitiateManager()
+{
+ gGrowlManager = new GrowlManager();
+}
+
diff --git a/indra/newview/growlmanager.h b/indra/newview/growlmanager.h
new file mode 100644
index 0000000000..14ebea5b73
--- /dev/null
+++ b/indra/newview/growlmanager.h
@@ -0,0 +1,71 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GROWLMANAGER_H
+#define GROWLMANAGER_H
+#include "growlnotifier.h"
+#include "lleventtimer.h"
+#include
+
+struct GrowlNotification
+{
+ std::string growlName;
+ std::string growlTitle;
+ std::string growlBody;
+ bool useDefaultTextForTitle;
+ bool useDefaultTextForBody;
+};
+
+const U64 GROWL_THROTTLE_TIME = 1000000; // Maximum spam rate (in microseconds).
+const F32 GROWL_THROTTLE_CLEANUP_PERIOD = 300; // How often we clean up the list (in seconds).
+const int GROWL_MAX_BODY_LENGTH = 255; // Arbitrary.
+
+class GrowlManager : public LLEventTimer
+{
+ LOG_CLASS(GrowlManager);
+public:
+
+ GrowlManager();
+ void notify(const std::string& notification_title, const std::string& notification_message, const std::string& notification_type);
+ BOOL tick();
+
+ static void InitiateManager();
+private:
+ GrowlNotifier *mNotifier;
+ std::map mNotifications;
+ std::map mTitleTimers;
+
+ void loadConfig();
+ static bool onLLNotification(const LLSD& notice);
+ static inline bool shouldNotify();
+};
+
+extern GrowlManager *gGrowlManager;
+
+#endif // GROWLMANAGER_H
diff --git a/indra/newview/growlnotifier.cpp b/indra/newview/growlnotifier.cpp
new file mode 100644
index 0000000000..300f0ebe31
--- /dev/null
+++ b/indra/newview/growlnotifier.cpp
@@ -0,0 +1,60 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "growlnotifier.h"
+
+GrowlNotifier::GrowlNotifier()
+{
+ // Nothing much?
+}
+GrowlNotifier::~GrowlNotifier()
+{
+
+}
+
+void GrowlNotifier::showNotification(const std::string& notification_title, const std::string& notification_message, const std::string& notification_type)
+{
+ //LL_WARNS("GrowlNotifierGeneric") << "Growl notification failed." << LL_ENDL;
+}
+
+bool GrowlNotifier::isUsable()
+{
+ return false; // Dummy implementation is not usable, obviously.
+}
+
+void GrowlNotifier::registerApplication(const std::string& application, const std::set& notificationTypes)
+{
+ //nothing special
+}
+
+bool GrowlNotifier::needsThrottle()
+{
+ return true; // Throttling is on by default.
+}
diff --git a/indra/newview/growlnotifier.h b/indra/newview/growlnotifier.h
new file mode 100644
index 0000000000..92b4edce1d
--- /dev/null
+++ b/indra/newview/growlnotifier.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GROWLNOTIFIER_H
+#define GROWLNOTIFIER_H
+
+#include
+
+class GrowlNotifier
+{
+public:
+ LOG_CLASS(GrowlNotifier);
+ GrowlNotifier();
+ virtual ~GrowlNotifier();
+ virtual void showNotification(const std::string& notification_title, const std::string& notification_message, const std::string& notification_type);
+ virtual bool isUsable();
+ virtual void registerApplication(const std::string& application, const std::set& notificationTypes);
+ virtual bool needsThrottle();
+};
+
+#endif // GROWLNOTIFIER_H
diff --git a/indra/newview/growlnotifiermacosx-objc.h b/indra/newview/growlnotifiermacosx-objc.h
new file mode 100644
index 0000000000..3ad870dbb0
--- /dev/null
+++ b/indra/newview/growlnotifiermacosx-objc.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GROWLNOTIFIERMACOSX_OBJC_H
+#define GROWLNOTIFIERMACOSX_OBJC_H
+#include
+#include
+
+void growlApplicationBridgeNotify(const std::string& withTitle, const std::string& description, const std::string& notificationName,
+ void *iconData, unsigned int iconDataSize, int priority, bool isSticky);
+void growlApplicationBridgeInit();
+void growlApplicationBridgeRegister(const std::string& appname, const std::set& notifications);
+bool growlApplicationBridgeIsGrowlInstalled();
+
+#endif // GROWLNOTIFIERMACOSX_OBJC_H
diff --git a/indra/newview/growlnotifiermacosx-objc.mm b/indra/newview/growlnotifiermacosx-objc.mm
new file mode 100644
index 0000000000..153ae122ca
--- /dev/null
+++ b/indra/newview/growlnotifiermacosx-objc.mm
@@ -0,0 +1,78 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "growlnotifiermacosx-objc.h"
+#import
+#import "Growl/Growl.h"
+
+@interface FirestormBridge : NSObject
+
+void growlApplicationBridgeNotify(const std::string& withTitle, const std::string& description, const std::string& notificationName,
+ void *iconData, unsigned int iconDataSize, int priority, bool isSticky) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [GrowlApplicationBridge notifyWithTitle:[NSString stringWithCString:withTitle.c_str() encoding:NSUTF8StringEncoding]
+ description:[NSString stringWithCString:description.c_str() encoding:NSUTF8StringEncoding]
+ notificationName:[NSString stringWithCString:notificationName.c_str() encoding:NSUTF8StringEncoding]
+ iconData:(iconData == NULL ? nil : [NSData dataWithBytes:iconData length:iconDataSize])
+ priority:priority
+ isSticky:isSticky
+ clickContext:nil
+ ];
+ [pool release];
+}
+
+void growlApplicationBridgeInit() {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+// [GrowlApplicationBridge setGrowlDelegate:@""];
+ [pool release];
+}
+
+bool growlApplicationBridgeIsGrowlInstalled() {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ bool installed = [GrowlApplicationBridge isGrowlInstalled];
+ [pool release];
+ return installed;
+}
+
+void growlApplicationBridgeRegister(const std::string& appname, const std::set& notifications)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSMutableArray *notificationArray = [[[NSMutableArray alloc] init] autorelease];
+ for(std::set::iterator itr = notifications.begin(); itr != notifications.end(); ++itr) {
+ [notificationArray addObject:[NSString stringWithCString:itr->c_str()]];
+ }
+ [GrowlApplicationBridge registerWithDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithCString:appname.c_str()], GROWL_APP_NAME,
+ notificationArray, GROWL_NOTIFICATIONS_ALL,
+ notificationArray, GROWL_NOTIFICATIONS_DEFAULT,
+ nil]];
+ [pool release];
+}
+
+@end
diff --git a/indra/newview/growlnotifiermacosx.cpp b/indra/newview/growlnotifiermacosx.cpp
new file mode 100644
index 0000000000..32da34aaba
--- /dev/null
+++ b/indra/newview/growlnotifiermacosx.cpp
@@ -0,0 +1,55 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "growlnotifiermacosx.h"
+#include "growlnotifiermacosx-objc.h"
+
+GrowlNotifierMacOSX::GrowlNotifierMacOSX()
+{
+ // Work around a Growl 1.1 bug whereby the app bridge *requires* a delegate.
+ growlApplicationBridgeInit();
+ LL_INFOS("GrowlNotifierOSX") << "OS X growl notifications initialised." << LL_ENDL;
+}
+
+void GrowlNotifierMacOSX::showNotification(const std::string& notification_title, const std::string& notification_message,
+ const std::string& notification_type)
+{
+ growlApplicationBridgeNotify(notification_title, notification_message, notification_type, NULL, 0, 0, false);
+}
+
+bool GrowlNotifierMacOSX::isUsable()
+{
+ return growlApplicationBridgeIsGrowlInstalled();
+}
+
+void GrowlNotifierMacOSX::registerApplication(const std::string& application, const std::set& notificationTypes)
+{
+ growlApplicationBridgeRegister(application, notificationTypes);
+}
\ No newline at end of file
diff --git a/indra/newview/growlnotifiermacosx.h b/indra/newview/growlnotifiermacosx.h
new file mode 100644
index 0000000000..5afe063d6f
--- /dev/null
+++ b/indra/newview/growlnotifiermacosx.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010 Katharine Berry All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. Neither the name Katharine Berry nor the names of any contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KATHARINE BERRY AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KATHARINE BERRY OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GROWLNOTIFIERMACOSX_H
+#define GROWLNOTIFIERMACOSX_H
+
+#include
+#include "growlnotifier.h"
+
+class GrowlNotifierMacOSX : public GrowlNotifier
+{
+public:
+ GrowlNotifierMacOSX();
+ ~GrowlNotifierMacOSX(){}
+
+ void showNotification(const std::string& notification_title, const std::string& notification_message, const std::string& notificationTypes);
+ bool isUsable();
+ void registerApplication(const std::string& application, const std::set& notificationTypes);
+};
+
+#endif // GROWLNOTIFIERMACOSX_H
diff --git a/indra/newview/growlnotifierwin.cpp b/indra/newview/growlnotifierwin.cpp
new file mode 100644
index 0000000000..93c1650574
--- /dev/null
+++ b/indra/newview/growlnotifierwin.cpp
@@ -0,0 +1,78 @@
+/* Copyright (c) 2009
+*
+* Greg Hendrickson (LordGregGreg Back). All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or
+* without modification, are permitted provided that the following
+* conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* 3. Neither the name Modular Systems nor the names of its contributors
+* may be used to endorse or promote products derived from this
+* software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "llviewerprecompiledheaders.h"
+#include "growlnotifierwin.h"
+#include "llviewercontrol.h"
+
+GrowlNotifierWin::GrowlNotifierWin():applicationName("")
+{
+ LL_INFOS("GrowlNotifierWin") << "Windows growl notifications initialised." << LL_ENDL;
+
+}
+void GrowlNotifierWin::registerApplication(const std::string& application, const std::set& notificationTypes)
+{
+ applicationName=application;
+
+ char **arr = (char**)malloc(sizeof(*arr) * notificationTypes.size());
+ int i = 0;
+ for(std::set::const_iterator it = notificationTypes.begin(); it != notificationTypes.end(); ++it, ++i) {
+ char *string = (char*)malloc(it->size() + 1);
+ strcpy(string, it->c_str());
+ arr[i] = string;
+ }
+ growl = new Growl(GROWL_TCP,NULL,application.c_str(),(const char **const)arr,notificationTypes.size(),
+ std::string(gDirUtilp->getDefaultSkinDir()+gDirUtilp->getDirDelimiter()+
+ "textures"+gDirUtilp->getDirDelimiter()+"firestorm_icon.png").c_str());
+ growl->setProtocol(GROWL_UDP);
+
+ for(i = 0; i < (int)notificationTypes.size(); ++i) {
+ free(arr[i]);
+ }
+ free(arr);
+}
+void GrowlNotifierWin::showNotification(const std::string& notification_title, const std::string& notification_message,
+ const std::string& notification_type)
+{
+ //LL_INFOS("GrowlNotifierWin") << std::string(gDirUtilp->getDefaultSkinDir()+gDirUtilp->getDirDelimiter()+"textures"+gDirUtilp->getDirDelimiter()+"phoenixicon.ico").c_str() << LL_ENDL;
+ growl->Notify(notification_type.c_str(),notification_title.c_str(),notification_message.c_str()
+ //,
+ //std::string("").c_str(),//url
+ //std::string("http://phoenixviewer.com/box/phoenixicon.ico").c_str()
+ );
+}
+
+bool GrowlNotifierWin::isUsable()
+{
+ //if(growl) return true;
+ return true;
+}
diff --git a/indra/newview/growlnotifierwin.h b/indra/newview/growlnotifierwin.h
new file mode 100644
index 0000000000..408c2517b1
--- /dev/null
+++ b/indra/newview/growlnotifierwin.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2009
+*
+* Greg Hendrickson (LordGregGreg Back). All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or
+* without modification, are permitted provided that the following
+* conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* 3. Neither the name Modular Systems nor the names of its contributors
+* may be used to endorse or promote products derived from this
+* software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GROWLNOTIFIERWIN_H
+#define GROWLNOTIFIERWIN_H
+
+#include "growlnotifier.h"
+#include
+
+class GrowlNotifierWin : public GrowlNotifier
+{
+public:
+ GrowlNotifierWin();
+ ~GrowlNotifierWin(){}
+
+ void showNotification(const std::string& notification_title, const std::string& notification_message, const std::string& notification_type);
+ bool isUsable();
+ void registerApplication(const std::string& application, const std::set& notificationTypes);
+private:
+ std::string applicationName;
+ Growl *growl;
+};
+
+#endif // GROWLNOTIFIERWIN_H
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 57ffedd697..4e31369d96 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -321,7 +321,15 @@ void LLNearbyChat::setVisible(BOOL visible)
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
if(chat_channel)
{
- chat_channel->removeToastsFromChannel();
+ chat_channel->hideToastsFromScreen();
+ }
+ }
+ else
+ {
+ LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
+ if(chat_channel)
+ {
+ chat_channel->showToastsOnScreen();
}
}
LLDockableFloater::setVisible(visible);
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index e7bfe7acc7..03ebf0d0d4 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -724,6 +724,13 @@ void LLScreenChannel::hideToastsFromScreen()
(*it).toast->setVisible(FALSE);
}
+//--------------------------------------------------------------------------
+void LLScreenChannel::showToastsOnScreen()
+{
+ for(std::vector::iterator it = mToastList.begin(); it != mToastList.end(); it++)
+ (*it).toast->setVisible(TRUE);
+}
+
//--------------------------------------------------------------------------
void LLScreenChannel::hideToast(const LLUUID& notification_id)
{
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index a1fdd6e32c..c3338b783d 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -77,6 +77,8 @@ public:
virtual void hideToastsFromScreen() {};
// removes all toasts from a channel
virtual void removeToastsFromChannel() {};
+ // show toasts that were hidden by hideToastsFromScreen()
+ virtual void showToastsOnScreen() {};
// show all toasts in a channel
virtual void redrawToasts() {};
@@ -169,6 +171,8 @@ public:
void hideToastsFromScreen();
// hide toast by notification id
void hideToast(const LLUUID& notification_id);
+ // show toasts that were hidden by hideToastsFromScreen()
+ void showToastsOnScreen();
/**
* Closes hidden matched toasts from channel.
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 4ea218ae8a..70b0c36e5d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -199,6 +199,7 @@
#endif
#include "llnotificationmanager.h"
+#include "growlmanager.h"
//
@@ -375,6 +376,8 @@ bool idle_startup()
// Initialize stuff that doesn't need data from simulators
//
+ GrowlManager::InitiateManager();
+
// [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0a) | Modified: RLVa-0.2.1d
if ( (gSavedSettings.controlExists(RLV_SETTING_MAIN)) && (gSavedSettings.getBOOL(RLV_SETTING_MAIN)) )
{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 33030aaa75..2cc9be65ac 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -117,6 +117,8 @@
#include "llnotificationmanager.h" //
+#include "growlmanager.h"
+
#if LL_MSVC
// disable boost::lexical_cast warning
#pragma warning (disable:4702)
@@ -2487,6 +2489,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
region_id,
position,
true);
+
+
+ // Notifications!
+ if(offline != IM_OFFLINE)
+ {
+ gGrowlManager->notify(name, message, "Instant Message received");
+ }
}
else
{
@@ -2953,6 +2962,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
params.payload = payload;
LLPostponedNotification::add(params, from_id, from_group);
+ gGrowlManager->notify(name, message, "Instant Message received");
}
break;
case IM_FROM_TASK_AS_ALERT:
diff --git a/indra/newview/res-sdl/firestorm_icon.png b/indra/newview/res-sdl/firestorm_icon.png
new file mode 100644
index 0000000000..a5e3fe25ab
Binary files /dev/null and b/indra/newview/res-sdl/firestorm_icon.png differ
diff --git a/indra/newview/res-sdl/firestorm_icon128.png b/indra/newview/res-sdl/firestorm_icon128.png
new file mode 100644
index 0000000000..a9940a9780
Binary files /dev/null and b/indra/newview/res-sdl/firestorm_icon128.png differ
diff --git a/indra/newview/skins/default/textures/firestorm_icon.png b/indra/newview/skins/default/textures/firestorm_icon.png
new file mode 100644
index 0000000000..a9940a9780
Binary files /dev/null and b/indra/newview/skins/default/textures/firestorm_icon.png differ
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index e08477b33e..083b5650ce 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -341,6 +341,12 @@ class WindowsManifest(ViewerManifest):
self.path("dbghelp.dll")
self.enable_no_crt_manifest_check()
+
+ #"G:\firestorm\lgpl\growl\libraries\i686-win32\lib\release\lgggrowl.dll"
+ if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'),dst="./"):
+ self.path("lgggrowl.dll")
+ self.path("lgggrowl++.dll")
+ self.end_prefix()
# Media plugins - QuickTime
if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
@@ -593,6 +599,9 @@ class DarwinManifest(ViewerManifest):
self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install")
+ # Growl library
+ self.path("../../libraries/universal-darwin/lib_release/libgrowl.dylib", "Frameworks/Growl.framework/Versions/A/Growl");
+
# most everything goes in the Resources directory
if self.prefix(src="", dst="Resources"):
super(DarwinManifest, self).construct()
@@ -976,6 +985,7 @@ class Linux_i686Manifest(LinuxManifest):
self.path("libalut.so")
self.path("libopenal.so", "libopenal.so.1")
self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
+ self.path("libnotify.so.1.1.2", "libnotify.so.1")
try:
self.path("libkdu.so")
pass
diff --git a/install.xml b/install.xml
index cbd00de220..5d1b6ff0f4 100644
--- a/install.xml
+++ b/install.xml
@@ -3,6 +3,39 @@
installables
+ Growl
+
+ copyright
+ The Growl Project
+ description
+ A unified notification system for Mac OS X
+ license
+ bsd
+ packages
+
+ darwin
+
+ md5sum
+ f075e96d8e1bfdd1f518829f0d7b74af
+ url
+ http://downloads.phoenixviewer.com/growl-1.2.1-darwin.tar.gz
+
+ windows
+
+ md5sum
+ b017cc5f759eaeb862a8b94d43a39c04
+ url
+ http://downloads.phoenixviewer.com/lggemwingrowllibraries.tar.bz2
+
+ linux
+
+ md5sum
+ af06208ec80b1f170cc560141602e2dc
+ url
+ http://downloads.phoenixviewer.com/libnotify-0.4.4-linux-20101003.tar.bz2
+
+
+
GL
copyright