aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in1
-rw-r--r--addons/resource.language.en_gb/resources/strings.po46
-rw-r--r--system/settings/settings.xml17
-rw-r--r--xbmc/GUIUserMessages.h4
-rw-r--r--xbmc/events/EventLog.cpp210
-rw-r--r--xbmc/events/EventLog.h75
-rw-r--r--xbmc/events/IEvent.h87
-rw-r--r--xbmc/events/Makefile7
8 files changed, 437 insertions, 10 deletions
diff --git a/Makefile.in b/Makefile.in
index 1f840bdc74..c97a84733b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -43,6 +43,7 @@ DIRECTORY_ARCHIVES=$(DVDPLAYER_ARCHIVES) \
xbmc/dbwrappers/dbwrappers.a \
xbmc/dialogs/dialogs.a \
xbmc/epg/epg.a \
+ xbmc/events/events.a \
xbmc/filesystem/MusicDatabaseDirectory/musicdatabasedirectory.a \
xbmc/filesystem/VideoDatabaseDirectory/videodatabasedirectory.a \
xbmc/filesystem/filesystem.a \
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 3fa1dbc367..38b8251e98 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -7129,7 +7129,7 @@ msgstr ""
#: system/settings/settings.xml
msgctxt "#14092"
-msgid "Debugging"
+msgid "Logging"
msgstr ""
msgctxt "#14093"
@@ -7224,7 +7224,21 @@ msgctxt "#14110"
msgid "Long date format"
msgstr ""
-#empty strings from id 14111 to 15003
+#empty string with id 14111
+
+#. Label of setting to enable/disable event logging
+#: system/settings/settings.xml
+msgctxt "#14112"
+msgid "Enable event logging"
+msgstr ""
+
+#. Label of setting to enable/disable event logging for notifications
+#: system/settings/settings.xml
+msgctxt "#14113"
+msgid "Enable notification event logging"
+msgstr ""
+
+#empty strings from id 14114 to 15003
#. Name of a class/preset for audio DSP
#: xbmc/settings/dialogs/GUIDialogAudioDSPSettings.cpp
@@ -16418,25 +16432,25 @@ msgctxt "#36390"
msgid "Define what action to perform when the shutdown function timer lapsed."
msgstr ""
-#. Description of settings category "System -> Debugging" with label #14092
+#. Description of settings category "System -> Logging" with label #14092
#: system/settings/settings.xml
msgctxt "#36391"
-msgid "This category contains the settings for enabling debug functions. You can also enable component-specific debug logging in order to help troubleshoot related issues in more detail."
+msgid "This category contains the settings for enabling event and debug logging. You can also enable component-specific debug logging in order to help troubleshoot related issues in more detail."
msgstr ""
-#. Description of setting "System -> Debugging -> Enable debug logging" with label #20191
+#. Description of setting "System -> Logging -> Enable debug logging" with label #20191
#: system/settings/settings.xml
msgctxt "#36392"
msgid "Turn debug logging on or off. Useful for troubleshooting."
msgstr ""
-#. Description of setting "System -> Debugging -> Screenshot folder" with label #20004
+#. Description of setting "System -> Logging -> Screenshot folder" with label #20004
#: system/settings/settings.xml
msgctxt "#36393"
msgid "Select the folder where screenshots should be saved in."
msgstr ""
-#. Description of setting "System -> Debugging -> Enable component-specific logging" with label #666
+#. Description of setting "System -> Logging -> Enable component-specific logging" with label #666
#: system/settings/settings.xml
msgctxt "#36394"
msgid "Enables verbose messages from additional libraries to be included in the debug log."
@@ -16709,7 +16723,21 @@ msgctxt "#36441"
msgid "Enable audio DSP processing"
msgstr ""
-#empty strings from id 36442 to 36499
+#empty strings from id 36459 to 36499
+
+#. Description of settings "System -> Logging -> Enable event logging" with label #14112
+#: system/settings/settings.xml
+msgctxt "#36460"
+msgid "Event logging allows to keep track of what has happened."
+msgstr ""
+
+#. Description of settings "System -> Logging -> Enable notification event logging" with label #14113
+#: system/settings/settings.xml
+msgctxt "#36461"
+msgid "Notification event describe regular processes and actions performed by the system or the user."
+msgstr ""
+
+#empty strings from id 36462 to 36499
#end reservation
@@ -16863,7 +16891,7 @@ msgctxt "#36533"
msgid "Select how audio is downmixed, e.g. from 5.1 to 2.0.[CR][Enabled] Maintains volume level of the original audio source however the dynamic range is compressed.[CR][Disabled] Maintains the dynamic range of the original audio source when downmixed however volume will be lower. Note: Dynamic range is the difference between the quietest and loudest sounds in an audio source. Enable this setting if movie dialogues are barely audible."
msgstr ""
-#. Description of setting "System -> Debugging -> Component-specific logging..." with label #668
+#. Description of setting "System -> Logging -> Component-specific logging..." with label #668
#: system/settings/settings.xml
msgctxt "#36534"
msgid "Specify additional libraries whose verbose messages are to be included in the debug log."
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 3b1cb6bc35..f9951cb6a0 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -2934,8 +2934,23 @@
</setting>
</group>
</category>
- <category id="debug" label="14092" help="36391">
+ <category id="logging" label="14092" help="36391">
<group id="1">
+ <setting id="eventlog.enabled" type="boolean" label="14112" help="36460">
+ <level>1</level>
+ <default>true</default>
+ <control type="toggle" />
+ </setting>
+ <setting id="eventlog.enablednotifications" type="boolean" parent="eventlog.enabled" label="14113" help="36461">
+ <level>1</level>
+ <default>false</default>
+ <dependencies>
+ <dependency type="enable" setting="eventlog.enabled" operator="is">true</dependency>
+ </dependencies>
+ <control type="toggle" />
+ </setting>
+ </group>
+ <group id="2">
<setting id="debug.showloginfo" type="boolean" label="20191" help="36392">
<level>1</level>
<default>false</default>
diff --git a/xbmc/GUIUserMessages.h b/xbmc/GUIUserMessages.h
index 86eaa2a45e..ce4ee2ea68 100644
--- a/xbmc/GUIUserMessages.h
+++ b/xbmc/GUIUserMessages.h
@@ -135,3 +135,7 @@
// Sent to text field to support 'input method'
#define GUI_MSG_INPUT_TEXT_EDIT GUI_MSG_USER + 38
+
+// Sent to CGUIWindowEventLog
+#define GUI_MSG_EVENT_ADDED GUI_MSG_USER + 39
+#define GUI_MSG_EVENT_REMOVED GUI_MSG_USER + 40
diff --git a/xbmc/events/EventLog.cpp b/xbmc/events/EventLog.cpp
new file mode 100644
index 0000000000..bd100ef248
--- /dev/null
+++ b/xbmc/events/EventLog.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2015 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "EventLog.h"
+#include "GUIUserMessages.h"
+#include "dialogs/GUIDialogKaiToast.h"
+#include "filesystem/EventsDirectory.h"
+#include "guilib/GUIWindowManager.h"
+#include "profiles/ProfilesManager.h"
+#include "settings/Settings.h"
+#include "threads/SingleLock.h"
+
+std::map<int, std::unique_ptr<CEventLog> > CEventLog::s_eventLogs;
+CCriticalSection CEventLog::s_critical;
+
+CEventLog& CEventLog::GetInstance()
+{
+ int currentProfileId = CProfilesManager::Get().GetCurrentProfileId();
+
+ CSingleLock lock(s_critical);
+ auto eventLog = s_eventLogs.find(currentProfileId);
+ if (eventLog == s_eventLogs.end())
+ {
+ s_eventLogs.insert(std::make_pair(currentProfileId, std::unique_ptr<CEventLog>(new CEventLog())));
+ eventLog = s_eventLogs.find(currentProfileId);
+ }
+
+ return *eventLog->second;
+}
+
+Events CEventLog::Get() const
+{
+ return m_events;
+}
+
+Events CEventLog::Get(EventLevel level, bool includeHigherLevels /* = false */) const
+{
+ Events events;
+
+ CSingleLock lock(m_critical);
+ for (const auto& eventPtr : m_events)
+ {
+ if (eventPtr->GetLevel() == level ||
+ (includeHigherLevels && eventPtr->GetLevel() > level))
+ events.push_back(eventPtr);
+ }
+
+ return events;
+}
+
+EventPtr CEventLog::Get(const std::string& eventPtrIdentifier) const
+{
+ if (eventPtrIdentifier.empty())
+ return EventPtr();
+
+ CSingleLock lock(m_critical);
+ const auto& eventPtr = m_eventsMap.find(eventPtrIdentifier);
+ if (eventPtr == m_eventsMap.end())
+ return EventPtr();
+
+ return eventPtr->second;
+}
+
+void CEventLog::Add(const EventPtr& eventPtr)
+{
+ if (eventPtr == nullptr || eventPtr->GetIdentifier().empty() ||
+ !CSettings::Get().GetBool("eventlog.enabled") ||
+ (eventPtr->GetLevel() == EventLevelInformation && !CSettings::Get().GetBool("eventlog.enablednotifications")))
+ return;
+
+ CSingleLock lock(m_critical);
+ if (m_eventsMap.find(eventPtr->GetIdentifier()) != m_eventsMap.end())
+ return;
+
+ // store the event
+ m_events.push_back(eventPtr);
+ m_eventsMap.insert(std::make_pair(eventPtr->GetIdentifier(), eventPtr));
+
+ SendMessage(eventPtr, GUI_MSG_EVENT_ADDED);
+}
+
+void CEventLog::Add(const EventPtr& eventPtr, bool withNotification, bool withSound /* = true */)
+{
+ if (!withNotification)
+ Add(eventPtr);
+ else
+ AddWithNotification(eventPtr, withSound);
+}
+
+void CEventLog::AddWithNotification(const EventPtr& eventPtr,
+ unsigned int displayTime /* = NOTIFICATION_DISPLAY_TIME */,
+ unsigned int messageTime /* = NOTIFICATION_MESSAGE_TIME */,
+ bool withSound /* = true */)
+{
+ if (eventPtr == nullptr)
+ return;
+
+ Add(eventPtr);
+
+ // queue the eventPtr as a kai toast notification
+ if (!eventPtr->GetIcon().empty())
+ CGUIDialogKaiToast::QueueNotification(eventPtr->GetIcon(), eventPtr->GetLabel(), eventPtr->GetDescription(), displayTime, withSound, messageTime);
+ else
+ {
+ CGUIDialogKaiToast::eMessageType type = CGUIDialogKaiToast::Info;
+ if (eventPtr->GetLevel() == EventLevelWarning)
+ type = CGUIDialogKaiToast::Warning;
+ else if (eventPtr->GetLevel() == EventLevelError)
+ type = CGUIDialogKaiToast::Error;
+
+ CGUIDialogKaiToast::QueueNotification(type, eventPtr->GetLabel(), eventPtr->GetDescription(), displayTime, withSound, messageTime);
+ }
+}
+
+void CEventLog::AddWithNotification(const EventPtr& eventPtr, bool withSound)
+{
+ AddWithNotification(eventPtr, NOTIFICATION_DISPLAY_TIME, NOTIFICATION_MESSAGE_TIME, withSound);
+}
+
+void CEventLog::Remove(const EventPtr& eventPtr)
+{
+ if (eventPtr == nullptr || eventPtr->GetIdentifier().empty())
+ return;
+
+ CSingleLock lock(m_critical);
+ const auto& itEvent = m_eventsMap.find(eventPtr->GetIdentifier());
+ if (itEvent == m_eventsMap.end())
+ return;
+
+ m_eventsMap.erase(itEvent);
+ std::remove_if(m_events.begin(), m_events.end(), [eventPtr](const EventPtr& otherEvent) { return eventPtr == otherEvent; });
+
+ SendMessage(eventPtr, GUI_MSG_EVENT_REMOVED);
+}
+
+void CEventLog::Remove(const std::string& eventPtrIdentifier)
+{
+ if (eventPtrIdentifier.empty())
+ return;
+
+ CSingleLock lock(m_critical);
+ const auto& itEvent = m_eventsMap.find(eventPtrIdentifier);
+ if (itEvent == m_eventsMap.end())
+ return;
+
+ EventPtr eventPtr = itEvent->second;
+ m_eventsMap.erase(itEvent);
+ std::remove_if(m_events.begin(), m_events.end(), [eventPtr](const EventPtr& otherEvent) { return eventPtr == otherEvent; });
+
+ SendMessage(eventPtr, GUI_MSG_EVENT_REMOVED);
+}
+
+void CEventLog::Clear()
+{
+ CSingleLock lock(m_critical);
+ m_events.clear();
+ m_eventsMap.clear();
+}
+
+void CEventLog::Clear(EventLevel level, bool includeHigherLevels /* = false */)
+{
+ EventsList eventsCopy = m_events;
+ for (const auto& eventPtr : eventsCopy)
+ {
+
+ if (eventPtr->GetLevel() == level ||
+ (includeHigherLevels && eventPtr->GetLevel() > level))
+ Remove(eventPtr);
+ }
+}
+
+bool CEventLog::Execute(const std::string& eventPtrIdentifier)
+{
+ if (eventPtrIdentifier.empty())
+ return false;
+
+ CSingleLock lock(m_critical);
+ const auto& itEvent = m_eventsMap.find(eventPtrIdentifier);
+ if (itEvent == m_eventsMap.end())
+ return false;
+
+ return itEvent->second->Execute();
+}
+
+void CEventLog::SendMessage(const EventPtr eventPtr, int message)
+{
+ CFileItemPtr item(new CFileItem(eventPtr->GetLabel()));
+ item->SetLabel2(eventPtr->GetDescription());
+ item->SetProperty("Event.ID", eventPtr->GetIdentifier());
+
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, message, 0, item);
+ g_windowManager.SendThreadMessage(msg);
+}
diff --git a/xbmc/events/EventLog.h b/xbmc/events/EventLog.h
new file mode 100644
index 0000000000..03b6787a98
--- /dev/null
+++ b/xbmc/events/EventLog.h
@@ -0,0 +1,75 @@
+#pragma once
+/*
+ * Copyright (C) 2015 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "events/IEvent.h"
+#include "threads/CriticalSection.h"
+
+#define NOTIFICATION_DISPLAY_TIME 5000
+#define NOTIFICATION_MESSAGE_TIME 1000
+
+typedef std::vector<EventPtr> Events;
+
+class CEventLog
+{
+public:
+ virtual ~CEventLog() { }
+
+ static CEventLog& GetInstance();
+
+ Events Get() const;
+ Events Get(EventLevel level, bool includeHigherLevels = false) const;
+ EventPtr Get(const std::string& eventIdentifier) const;
+
+ void Add(const EventPtr& event);
+ void Add(const EventPtr& event, bool withNotification, bool withSound = true);
+ void AddWithNotification(const EventPtr& event,
+ unsigned int displayTime = NOTIFICATION_DISPLAY_TIME,
+ unsigned int messageTime = NOTIFICATION_MESSAGE_TIME,
+ bool withSound = true);
+ void AddWithNotification(const EventPtr& event, bool withSound);
+ void Remove(const EventPtr& event);
+ void Remove(const std::string& eventIdentifier);
+ void Clear();
+ void Clear(EventLevel level, bool includeHigherLevels = false);
+
+ bool Execute(const std::string& eventIdentifier);
+
+protected:
+ CEventLog() { }
+ CEventLog(const CEventLog&);
+ CEventLog const& operator=(CEventLog const&);
+
+private:
+ void SendMessage(const EventPtr event, int message);
+
+ typedef std::vector<EventPtr> EventsList;
+ typedef std::map<std::string, EventPtr> EventsMap;
+ EventsList m_events;
+ EventsMap m_eventsMap;
+ CCriticalSection m_critical;
+
+ static std::map<int, std::unique_ptr<CEventLog> > s_eventLogs;
+ static CCriticalSection s_critical;
+};
diff --git a/xbmc/events/IEvent.h b/xbmc/events/IEvent.h
new file mode 100644
index 0000000000..9aabd1ef37
--- /dev/null
+++ b/xbmc/events/IEvent.h
@@ -0,0 +1,87 @@
+#pragma once
+/*
+ * Copyright (C) 2015 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <memory>
+#include <string>
+
+class CDateTime;
+
+typedef enum EventLevel
+{
+ EventLevelBasic = 0,
+ EventLevelInformation,
+ EventLevelWarning,
+ EventLevelError
+} EventLevel;
+
+static std::string EventLevelToString(EventLevel level)
+{
+ switch (level)
+ {
+ case EventLevelBasic:
+ return "basic";
+
+ case EventLevelWarning:
+ return "warning";
+
+ case EventLevelError:
+ return "error";
+
+ case EventLevelInformation:
+ default:
+ break;
+ }
+
+ return "information";
+}
+
+static EventLevel EventLevelFromString(const std::string& level)
+{
+ if (level == "basic")
+ return EventLevelBasic;
+ if (level == "warning")
+ return EventLevelWarning;
+ if (level == "error")
+ return EventLevelError;
+
+ return EventLevelInformation;
+}
+
+class IEvent
+{
+public:
+ virtual ~IEvent() { }
+
+ virtual const char* GetType() const = 0;
+ virtual std::string GetIdentifier() const = 0;
+ virtual EventLevel GetLevel() const = 0;
+ virtual std::string GetLabel() const = 0;
+ virtual std::string GetIcon() const = 0;
+ virtual std::string GetDescription() const = 0;
+ virtual std::string GetDetails() const = 0;
+ virtual std::string GetExecutionLabel() const = 0;
+ virtual CDateTime GetDateTime() const = 0;
+
+ virtual bool CanExecute() const = 0;
+ virtual bool Execute() const = 0;
+};
+
+typedef std::shared_ptr<const IEvent> EventPtr;
diff --git a/xbmc/events/Makefile b/xbmc/events/Makefile
new file mode 100644
index 0000000000..d39aa339c9
--- /dev/null
+++ b/xbmc/events/Makefile
@@ -0,0 +1,7 @@
+SRCS=EventLog.cpp \
+
+LIB=events.a
+
+include ../../Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
+