diff --git a/CMakeLists.txt b/CMakeLists.txt index 6646d8047..f2cd411c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ option(WITH_BREAKPAD "Build with breakpad integration" ON) option(WITH_CRASHREPORTER "Build with CrashReporter" ON) option(WITH_BINARY_ATTICA "Enable support for downloading binary resolvers automatically" ON) option(LEGACY_KDE_INTEGRATION "Install tomahawk.protocol file, deprecated since 4.6.0" OFF) +OPTION(WITH_UPOWER "Build with support for UPower events" OFF) IF( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" ) message(STATUS "Build of breakpad library disabled on this platform.") @@ -186,6 +187,10 @@ if(BUILD_GUI AND UNIX AND NOT APPLE) find_package( X11 ) endif() +IF( UNIX AND NOT APPLE AND QT_QTDBUS_FOUND ) + SET( WITH_UPOWER ON ) +ENDIF( UNIX AND NOT APPLE AND QT_QTDBUS_FOUND ) + macro_optional_find_package(Phonon 4.5.0) macro_log_feature(PHONON_FOUND "Phonon" "The Phonon multimedia library" "http://phonon.kde.org" TRUE "" "") if(PHONON_FOUND) diff --git a/src/tomahawk/CMakeLists.linux.cmake b/src/tomahawk/CMakeLists.linux.cmake index e3e207fa1..30f0ee538 100644 --- a/src/tomahawk/CMakeLists.linux.cmake +++ b/src/tomahawk/CMakeLists.linux.cmake @@ -5,6 +5,11 @@ FOREACH( _file ${_icons} ) INSTALL( FILES ${_file} RENAME tomahawk.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${_res}/apps ) ENDFOREACH( _file ) +IF( WITH_UPOWER ) + QT4_ADD_DBUS_INTERFACE(tomahawkSources "${CMAKE_CURRENT_SOURCE_DIR}/linux/org.freedesktop.UPower.xml" linux/UPowerProxy) +ENDIF( WITH_UPOWER ) +ADD_SUBDIRECTORY( "${CMAKE_CURRENT_SOURCE_DIR}/linux" ) + INSTALL( FILES ${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon.svg RENAME tomahawk.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps ) INSTALL( FILES ${CMAKE_SOURCE_DIR}/admin/unix/tomahawk.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications ) diff --git a/src/tomahawk/Config.h.in b/src/tomahawk/Config.h.in index 79e5bad39..33effc143 100644 --- a/src/tomahawk/Config.h.in +++ b/src/tomahawk/Config.h.in @@ -18,6 +18,7 @@ #cmakedefine WITH_CRASHREPORTER #cmakedefine WITH_BINARY_ATTICA #cmakedefine WITH_QtSparkle +#cmakedefine WITH_UPOWER #cmakedefine LIBLASTFM_FOUND diff --git a/src/tomahawk/TomahawkApp.cpp b/src/tomahawk/TomahawkApp.cpp index 4f1c6d558..927334f17 100644 --- a/src/tomahawk/TomahawkApp.cpp +++ b/src/tomahawk/TomahawkApp.cpp @@ -79,6 +79,10 @@ #include "config.h" +#ifdef WITH_UPOWER + #include "linux/UPowerHandler.h" +#endif + #ifndef ENABLE_HEADLESS #include #endif @@ -148,6 +152,7 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] ) setOrganizationDomain( QLatin1String( TOMAHAWK_ORGANIZATION_DOMAIN ) ); setApplicationName( QLatin1String( TOMAHAWK_APPLICATION_NAME ) ); setApplicationVersion( QLatin1String( TOMAHAWK_VERSION ) ); + connect( this, SIGNAL( tomahawkLoaded() ), SLOT( initEnergyEventHandler() ) ); registerMetaTypes(); TomahawkUtils::installTranslator( this ); @@ -633,6 +638,15 @@ TomahawkApp::initFactoriesForAccountManager() Tomahawk::Accounts::AccountManager::instance()->loadFromConfig(); } +void +TomahawkApp::initEnergyEventHandler() +{ +#ifdef WITH_UPOWER + UPowerHandler* upower = new UPowerHandler( this ); + upower->registerHandler(); +#endif // WITH_UPOWER +} + // This method will be called twice during Tomahawk startup. // We don't know which is going to be ready first, AccountManager or Servent, but this goes through diff --git a/src/tomahawk/TomahawkApp.h b/src/tomahawk/TomahawkApp.h index 761e63fdb..aca7eb1a7 100644 --- a/src/tomahawk/TomahawkApp.h +++ b/src/tomahawk/TomahawkApp.h @@ -112,6 +112,7 @@ private slots: void initSIP(); void initHTTP(); void initFactoriesForAccountManager(); + void initEnergyEventHandler(); void spotifyApiCheckFinished(); diff --git a/src/tomahawk/linux/CMakeLists.txt b/src/tomahawk/linux/CMakeLists.txt new file mode 100644 index 000000000..29a7d697d --- /dev/null +++ b/src/tomahawk/linux/CMakeLists.txt @@ -0,0 +1,3 @@ +IF( WITH_UPOWER ) + SET( tomahawkSources ${tomahawkSources} "${CMAKE_CURRENT_SOURCE_DIR}/UPowerHandler.cpp" PARENT_SCOPE ) +ENDIF( WITH_UPOWER ) diff --git a/src/tomahawk/linux/UPowerHandler.cpp b/src/tomahawk/linux/UPowerHandler.cpp new file mode 100644 index 000000000..e5a74c0c8 --- /dev/null +++ b/src/tomahawk/linux/UPowerHandler.cpp @@ -0,0 +1,79 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Uwe L. Korn + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#include "accounts/AccountManager.h" +#include "UPowerHandler.h" +#include "utils/Logger.h" + +#include + +#define UPOWER_RESUME_DELAY 2000 + +using namespace Tomahawk; + +const char* UPowerHandler::UPowerService = "org.freedesktop.UPower"; +const char* UPowerHandler::UPowerPath = "/org/freedesktop/UPower"; +const char* UPowerHandler::UPowerInterface = "org.freedesktop.UPower"; + +Tomahawk::UPowerHandler::UPowerHandler( QObject *parent ) + : QObject( parent ) +{ +} + +bool +UPowerHandler::registerHandler() +{ + // Check if the UPower is available + if ( !QDBusConnection::systemBus().interface()->isServiceRegistered( UPowerService ) ) { + tLog( LOGVERBOSE ) << Q_FUNC_INFO << "UPower is not available"; + return false; + } + + tLog( LOGVERBOSE ) << Q_FUNC_INFO << "UPower available, will reconnect on wake from suspend."; + if ( m_interface.isNull() ) + { + m_interface = QSharedPointer( new org::freedesktop::UPower( UPowerService, UPowerPath, QDBusConnection::systemBus(), this ) ); + } + connect( m_interface.data(), SIGNAL( Sleeping() ), this, SLOT( handleSleep() )); + connect( m_interface.data(), SIGNAL( Resuming() ), this, SLOT( handleResume() )); + return true; +} + +void +UPowerHandler::handleSleep() +{ + QMutexLocker locker( &m_mutex ); + tLog( LOGVERBOSE ) << Q_FUNC_INFO << "About to sleep so disconnecting all accounts"; + Tomahawk::Accounts::AccountManager::instance()->disconnectAll(); +} + +void +UPowerHandler::handleResume() +{ + m_mutex.lock(); + // Delay resuming for other wakeup actions, e.g. reconnecting to the network, to take place. + QTimer::singleShot( UPOWER_RESUME_DELAY, this, SLOT( actualResume() ) ); +} + +void +UPowerHandler::actualResume() +{ + tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Awake from sleep so connecting all accounts"; + Tomahawk::Accounts::AccountManager::instance()->connectAll(); + m_mutex.unlock(); +} diff --git a/src/tomahawk/linux/UPowerHandler.h b/src/tomahawk/linux/UPowerHandler.h new file mode 100644 index 000000000..9ee501edf --- /dev/null +++ b/src/tomahawk/linux/UPowerHandler.h @@ -0,0 +1,52 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Uwe L. Korn + * + * Tomahawk 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 3 of the License, or + * (at your option) any later version. + * + * Tomahawk 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 Tomahawk. If not, see . + */ + +#ifndef UPOWERHANDLER_H +#define UPOWERHANDLER_H + +#include "linux/UPowerProxy.h" + +#include +#include +#include + +namespace Tomahawk { + +class UPowerHandler : public QObject +{ + Q_OBJECT +public: + explicit UPowerHandler( QObject *parent = 0 ); + bool registerHandler(); + + static const char* UPowerService; + static const char* UPowerPath; + static const char* UPowerInterface; +private: + QSharedPointer m_interface; + QMutex m_mutex; + +private slots: + void handleSleep(); + void handleResume(); + void actualResume(); +}; + +} + +#endif // UPOWERHANDLER_H diff --git a/src/tomahawk/linux/org.freedesktop.UPower.xml b/src/tomahawk/linux/org.freedesktop.UPower.xml new file mode 100644 index 000000000..9582ab5df --- /dev/null +++ b/src/tomahawk/linux/org.freedesktop.UPower.xml @@ -0,0 +1,395 @@ + + + + + + + + The UPower service is available via the system message + bus. To access the service, use + the org.freedesktop.UPower interface on + the /org/freedesktop/UPower object on + the D-Bus system bus service with the well-known + name org.freedesktop.UPower. + + + + +$ dbus-send --print-reply \ + --system \ + --dest=org.freedesktop.UPower \ + /org/freedesktop/UPower \ + org.freedesktop.UPower.EnumerateDevices + +method return sender=:1.386 -> dest=:1.451 reply_serial=2 + array [ + object path "/org/freedesktop/UPower/devices/line_power_AC" + object path "/org/freedesktop/UPower/devices/battery_BAT0" + ] + + + + + + + + + + + + An array of object paths for devices. + + + + + + Enumerate all power objects on the system. + + + + + + + + + + Object path of device that was added. + + + + + + Emitted when a device is added. + + + + + + + + + + Object path of device that was removed. + + + + + + Emitted when a device is removed. + + + + + + + + + + Object path of device that was changed. + + + + + + Emitted when a device changed. + + + + + + + + + + + + Emitted when one or more properties on the object changes. + + + + + + + + + + + + This signal is sent when the session is about to be suspended or + hibernated. + + + This signal is DEPRECATED. Use NotifySleep() instead. + + + + + + + + + + + + This signal is sent when the session is about to be suspended or + hibernated. + Session and system programs have one second to do anything required + before the sleep action is taken (such as sending out Avahi or + Jabber messages). + + + + + + + The sleep action type, e.g. suspend, + hibernate or hybrid. + + + + + + + + + + + + This signal is sent when the session has just returned from + Suspend() or Hibernate(). + + + This signal is DEPRECATED. Use NotifyResume() instead. + + + + + + + + + + + + This signal is sent when the session has just returned from + Suspend() or Hibernate(). + Session and system programs can then do anything required (such as + sending out Avahi or Jabber messages). + + + + + + + The sleep action type, e.g. suspend, + hibernate or hybrid. + + + + + + + + + + + + + This method tells UPower that the Suspend() or Hibernate() method + is about to be called. + This allows UPower to emit the Suspending signal whilst + session activities are happening that have to be done before the + suspend process is started. + + + This method would typically be called by the session power + management daemon, before it locks the screen and waits for the + screen to fade to black. + The session power management component would then call Suspend() or + Hibernate() when these syncronous tasks have completed. + + + If this method is not called than nothing bad will happen and + Suspend() or Hibernate() will block for the required second. + + + + + + + The sleep action type, e.g. suspend or + hibernate. + + + + + + + + + + + + + Suspends the computer into a low power state. + System state is not preserved if the power is lost. + + + If AboutToSleep() has not been called then UPower will send + the Sleeping() signal and block for one second. + + + If AboutToSleep() has been called less than one second + before this method is called then UPower will block for the + remaining time to complete one second of delay. + + + + + + + + + + + TRUE if allowed, otherwise FALSE + + + + + Check if the caller has (or can get) the PolicyKit privilege to call + Suspend. + + + + + + + + + + + + + Hibernates the computer into a low power state. + System state is preserved if the power is lost. + + + If AboutToSleep() has not been called then UPower will send + the Sleeping() signal and block for one second. + + + If AboutToSleep() has been called less than one second + before this method is called then UPower will block for the + remaining time to complete one second of delay. + + + + + + + + + + + TRUE if allowed, otherwise FALSE + + + + + Check if the caller has (or can get) the PolicyKit privilege to call + Hibernate. + + + + + + + + + + Version of the running daemon, e.g. 002. + + + + + + Whether the system is able to suspend. + + + + + + Whether the system is able to hibernate. + + + + + + Indicates whether the system is running on battery power. + This property is provided for convenience. + + + + + + Indicates whether the system is running on battery power and if the battery is critically low. + This property is provided for convenience. + + + + + + + + Indicates if the laptop lid is closed where the display cannot be seen. + + + + + + + + + + If the system has a lid device. + + + + + + + + + + If the system really has to sleep when the lid is closed. + Some laptops actually melt (!) if the lid is closed and the + computer keeps running. We blacklist those, and do something + sane for the other machines. + + + This allows us to set the default session policy to not + suspend on lid close if the laptop is docked, and be sure + the machine is not going to melt. + + + + + + + + + + If the system is currently docked. + Note: the "is-docked" value is the result of a heuristic, + which may involve testing the display output. + + + + + + + +