diff options
-rw-r--r-- | Makefile.in | 1 | ||||
-rw-r--r-- | addons/resource.language.en_gb/resources/strings.po | 46 | ||||
-rw-r--r-- | system/settings/settings.xml | 17 | ||||
-rw-r--r-- | xbmc/GUIUserMessages.h | 4 | ||||
-rw-r--r-- | xbmc/events/EventLog.cpp | 210 | ||||
-rw-r--r-- | xbmc/events/EventLog.h | 75 | ||||
-rw-r--r-- | xbmc/events/IEvent.h | 87 | ||||
-rw-r--r-- | xbmc/events/Makefile | 7 |
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))) + |