diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a039a1ed..1d12b908d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,8 +144,8 @@ if (TAGLIB_FOUND) endif (TAGLIB_FOUND) if (NOT WIN32) - set(CANTATA_SRCS ${CANTATA_SRCS} dbus/mpris.cpp dbus/gnomemediakeys.cpp devices/mountpoints.cpp) - set(CANTATA_MOC_HDRS ${CANTATA_MOC_HDRS} dbus/mpris.h dbus/gnomemediakeys.h devices/mountpoints.h) + set(CANTATA_SRCS ${CANTATA_SRCS} dbus/mpris.cpp dbus/gnomemediakeys.cpp devices/mountpoints.cpp dbus/powermanagement.cpp) + set(CANTATA_MOC_HDRS ${CANTATA_MOC_HDRS} dbus/mpris.h dbus/gnomemediakeys.h devices/mountpoints.h dbus/powermanagement.h) set(CANTATA_SRCS ${CANTATA_SRCS} dbus/notify.cpp) set(CANTATA_MOC_HDRS ${CANTATA_MOC_HDRS} dbus/notify.h) endif (NOT WIN32) @@ -195,6 +195,8 @@ if (NOT WIN32) qt5_add_dbus_interfaces(CANTATA_SRCS dbus/org.freedesktop.UPower.xml) qt5_add_dbus_interfaces(CANTATA_SRCS dbus/org.gnome.SettingsDaemon.xml) qt5_add_dbus_interfaces(CANTATA_SRCS dbus/org.gnome.SettingsDaemon.MediaKeys.xml) + qt5_add_dbus_interfaces(CANTATA_SRCS dbus/org.kde.Solid.PowerManagement.PolicyAgent.xml) + qt5_add_dbus_interfaces(CANTATA_SRCS dbus/org.freedesktop.PowerManagement.Inhibit.xml) else (ENABLE_QT5) if ( (QT_VERSION_MINOR LESS 8) OR (QT_VERSION_MINOR EQUAL 8 AND QT_VERSION_PATCH LESS 4) ) qt4_add_dbus_adaptor(CANTATA_SRCS dbus/org.mpris.MediaPlayer2.Player.OLD.xml dbus/mpris.h Mpris) @@ -213,6 +215,8 @@ if (NOT WIN32) endif (NOT ENABLE_KDE_SUPPORT) qt4_add_dbus_interfaces(CANTATA_SRCS dbus/org.gnome.SettingsDaemon.xml) qt4_add_dbus_interfaces(CANTATA_SRCS dbus/org.gnome.SettingsDaemon.MediaKeys.xml) + qt4_add_dbus_interfaces(CANTATA_SRCS dbus/org.kde.Solid.PowerManagement.PolicyAgent.xml) + qt4_add_dbus_interfaces(CANTATA_SRCS dbus/org.freedesktop.PowerManagement.Inhibit.xml) endif (ENABLE_QT5) endif (NOT WIN32) diff --git a/ChangeLog b/ChangeLog index 968c49a2a..acca71e83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,7 +21,8 @@ file format. 9. Use QListWidget in Qt preferences dialog, so that keyboard navigation can be used. -10. Add ability to 'filter' search stream categories. +10. Add ability to 'filter search' stream categories. +11. Add option to prevent system from suspending whilst playing (Linux only). 1.1.2 ----- diff --git a/dbus/org.freedesktop.PowerManagement.Inhibit.xml b/dbus/org.freedesktop.PowerManagement.Inhibit.xml new file mode 100644 index 000000000..d5be190b5 --- /dev/null +++ b/dbus/org.freedesktop.PowerManagement.Inhibit.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dbus/org.kde.Solid.PowerManagement.PolicyAgent.xml b/dbus/org.kde.Solid.PowerManagement.PolicyAgent.xml new file mode 100644 index 000000000..a07dd73fe --- /dev/null +++ b/dbus/org.kde.Solid.PowerManagement.PolicyAgent.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/dbus/powermanagement.cpp b/dbus/powermanagement.cpp new file mode 100644 index 000000000..f658fb99b --- /dev/null +++ b/dbus/powermanagement.cpp @@ -0,0 +1,105 @@ +/* + * Cantata + * + * Copyright (c) 2011-2013 Craig Drummond + * + * ---- + * + * 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 of the License, 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "powermanagement.h" + +#ifdef ENABLE_KDE_SUPPORT +#include +#include +K_GLOBAL_STATIC(PowerManagement, instance) +#else +#include "inhibitinterface.h" +#include "policyagentinterface.h" +#include "upowerinterface.h" +#endif + +PowerManagement * PowerManagement::self() +{ + #ifdef ENABLE_KDE_SUPPORT + return instance; + #else + static PowerManagement *instance=0; + if(!instance) { + instance=new PowerManagement; + } + return instance; + #endif +} + +PowerManagement::PowerManagement() + : cookie(-1) +{ + #ifdef ENABLE_KDE_SUPPORT + #if KDE_IS_VERSION(4, 7, 0) + connect(Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), this, SIGNAL(resuming())); + #endif + #else + policy = new OrgKdeSolidPowerManagementPolicyAgentInterface(OrgKdeSolidPowerManagementPolicyAgentInterface::staticInterfaceName(), + QLatin1String("/org/kde/Solid/PowerManagement/PolicyAgent"), + QDBusConnection::sessionBus(), this); + inhibit = new OrgFreedesktopPowerManagementInhibitInterface(OrgFreedesktopPowerManagementInhibitInterface::staticInterfaceName(), + QLatin1String("/org/freedesktop/PowerManagement/Inhibit"), + QDBusConnection::sessionBus(), this); + upower = new OrgFreedesktopUPowerInterface(OrgFreedesktopUPowerInterface::staticInterfaceName(), + QLatin1String("/org/freedesktop/UPower"), QDBusConnection::systemBus(), this); + connect(upower, SIGNAL(Resuming()), this, SIGNAL(resuming())); + #endif +} + +void PowerManagement::beginSuppressingSleep(const QString &reason) +{ + if (-1!=cookie) { + return; + } + #ifdef ENABLE_KDE_SUPPORT + cookie=Solid::PowerManagement::beginSuppressingSleep(reason); + #else + QDBusReply reply; + if (policy->isValid()) { + reply = policy->AddInhibition((uint)1, QCoreApplication::applicationName(), reason); + } else { + // Fallback to the fd.o Inhibit interface + reply = inhibit->Inhibit(QCoreApplication::applicationName(), reason); + } + cookie=reply.isValid() ? reply : -1; + #endif +} + +void PowerManagement::stopSuppressingSleep() +{ + if (-1==cookie) { + return; + } + + #ifdef ENABLE_KDE_SUPPORT + Solid::PowerManagement::stopSuppressingSleep(cookie); + #else + if (policy->isValid()) { + policy->ReleaseInhibition(cookie); + } else { + // Fallback to the fd.o Inhibit interface + inhibit->UnInhibit(cookie); + } + #endif + cookie=-1; +} diff --git a/dbus/powermanagement.h b/dbus/powermanagement.h new file mode 100644 index 000000000..af6678534 --- /dev/null +++ b/dbus/powermanagement.h @@ -0,0 +1,58 @@ +/* + * Cantata + * + * Copyright (c) 2011-2013 Craig Drummond + * + * ---- + * + * 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 of the License, 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef POWERMANAGEMENT_H +#define POWERMANAGEMENT_H + +#include +#include + +#ifndef ENABLE_KDE_SUPPORT +class OrgKdeSolidPowerManagementPolicyAgentInterface; +class OrgFreedesktopPowerManagementInhibitInterface; +class OrgFreedesktopUPowerInterface; +#endif + +class PowerManagement : public QObject +{ +Q_OBJECT +public: + static PowerManagement * self(); + PowerManagement(); + + void beginSuppressingSleep(const QString &reason = QString()); + void stopSuppressingSleep(); + +Q_SIGNALS: + void resuming(); + +private: + int cookie; + #ifndef ENABLE_KDE_SUPPORT + OrgKdeSolidPowerManagementPolicyAgentInterface *policy; + OrgFreedesktopPowerManagementInhibitInterface *inhibit; + OrgFreedesktopUPowerInterface *upower; + #endif +}; + +#endif diff --git a/gui/application.cpp b/gui/application.cpp index 37cef1ee2..db8b71726 100644 --- a/gui/application.cpp +++ b/gui/application.cpp @@ -26,7 +26,6 @@ #ifdef ENABLE_KDE_SUPPORT #include #include -#include #include "initialsettingswizard.h" #else #include @@ -49,9 +48,7 @@ Application::Application(Display *display, Qt::HANDLE visual, Qt::HANDLE colorma : KUniqueApplication(display, visual, colormap) , w(0) { - #if KDE_IS_VERSION(4, 7, 0) - connect(Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), MPDConnection::self(), SLOT(reconnect())); - #endif + connect(PowerManagement::self(), SIGNAL(resuming()), MPDConnection::self(), SLOT(reconnect())); } #endif @@ -59,9 +56,6 @@ Application::Application() : KUniqueApplication() , w(0) { - #if KDE_IS_VERSION(4, 7, 0) - connect(Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), MPDConnection::self(), SLOT(reconnect())); - #endif } Application::~Application() { @@ -226,7 +220,6 @@ void Application::load(const QStringList &files) #include #include #include -#include "upowerinterface.h" Application::Application(int &argc, char **argv) : QApplication(argc, argv) @@ -236,7 +229,6 @@ Application::Application(int &argc, char **argv) bool Application::start() { if (QDBusConnection::sessionBus().registerService(CANTATA_REV_URL)) { - connectPowerSignal(); setupIconTheme(); return true; } @@ -284,15 +276,4 @@ void Application::loadFiles() #endif } -void Application::connectPowerSignal() -{ - if (!QDBusConnection::systemBus().interface()->isServiceRegistered(OrgFreedesktopUPowerInterface::staticInterfaceName())) { - QDBusConnection::systemBus().interface()->startService(OrgFreedesktopUPowerInterface::staticInterfaceName()); - } - - OrgFreedesktopUPowerInterface *upower=new OrgFreedesktopUPowerInterface(OrgFreedesktopUPowerInterface::staticInterfaceName(), - "/org/freedesktop/UPower", QDBusConnection::systemBus(), this); - connect(upower, SIGNAL(Resuming()), MPDConnection::self(), SLOT(reconnect())); -} - #endif diff --git a/gui/application.h b/gui/application.h index 2fbc49e3f..ba6a6cc26 100644 --- a/gui/application.h +++ b/gui/application.h @@ -87,7 +87,6 @@ public: void loadFiles(); void setActivationWindow(QWidget *) { } void setupIconTheme(); - void connectPowerSignal(); }; #endif diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index bb150764c..f6661fd42 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -1362,6 +1362,7 @@ void MainWindow::readSettings() if (gnomeMediaKeys) { gnomeMediaKeys->setEnabled(Settings::self()->gnomeMediaKeys()); } + MPDStatus::setInhibitSuspend(Settings::self()->inhibitSuspend()); #endif context->readConfig(); } diff --git a/gui/playbacksettings.cpp b/gui/playbacksettings.cpp index 736a57f00..f2e88d72e 100644 --- a/gui/playbacksettings.cpp +++ b/gui/playbacksettings.cpp @@ -30,6 +30,11 @@ #include "messagebox.h" #include +#define REMOVE(w) \ + w->setVisible(false); \ + w->deleteLater(); \ + w=0; + PlaybackSettings::PlaybackSettings(QWidget *p) : QWidget(p) { @@ -57,6 +62,10 @@ PlaybackSettings::PlaybackSettings(QWidget *p) messageIcon->setMinimumSize(iconSize, iconSize); messageIcon->setMaximumSize(iconSize, iconSize); mpdConnectionStateChanged(MPDConnection::self()->isConnected()); + #ifdef Q_OS_WIN + REMOVE(inhibitSuspendLabel) + REMOVE(inhibitSuspend) + #endif } void PlaybackSettings::load() @@ -64,6 +73,9 @@ void PlaybackSettings::load() stopOnExit->setChecked(Settings::self()->stopOnExit()); stopFadeDuration->setValue(Settings::self()->stopFadeDuration()); stopDynamizerOnExit->setChecked(Settings::self()->stopDynamizerOnExit()); + #ifndef Q_OS_WIN + inhibitSuspend->setChecked(Settings::self()->inhibitSuspend()); + #endif crossfading->setValue(MPDStatus::self()->crossFade()); if (MPDConnection::self()->isConnected()) { @@ -77,6 +89,9 @@ void PlaybackSettings::save() Settings::self()->saveStopOnExit(stopOnExit->isChecked()); Settings::self()->saveStopFadeDuration(stopFadeDuration->value()); Settings::self()->saveStopDynamizerOnExit(stopDynamizerOnExit->isChecked()); + #ifndef Q_OS_WIN + Settings::self()->saveInhibitSuspend(inhibitSuspend->isChecked()); + #endif if (MPDConnection::self()->isConnected()) { emit setCrossFade(crossfading->value()); diff --git a/gui/playbacksettings.ui b/gui/playbacksettings.ui index 3553fca1c..2ad3b86b9 100644 --- a/gui/playbacksettings.ui +++ b/gui/playbacksettings.ui @@ -129,7 +129,7 @@ - Stopping Playback + Playback @@ -178,7 +178,40 @@ - + + + + Inhibit suspend whilst playing: + + + inhibitSuspend + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + + <i><b>NOTE:</b> If you press and hold the stop button, then a menu will be shown allowing you to choose whether to stop playback now, or after the current track.</i> @@ -235,6 +268,7 @@ stopFadeDuration stopOnExit stopDynamizerOnExit + inhibitSuspend diff --git a/gui/settings.cpp b/gui/settings.cpp index b2d1e867c..098cba6b9 100644 --- a/gui/settings.cpp +++ b/gui/settings.cpp @@ -692,6 +692,13 @@ QStringList Settings::hiddenStreamCategories() return GET_STRINGLIST("hiddenStreamCategories", QStringList()); } +#ifndef Q_OS_WIN32 +bool Settings::inhibitSuspend() +{ + return GET_BOOL("inhibitSuspend", false); +} +#endif + void Settings::removeConnectionDetails(const QString &v) { if (v==currentConnection()) { @@ -1104,6 +1111,13 @@ void Settings::saveHiddenStreamCategories(const QStringList &v) SET_VALUE_MOD(hiddenStreamCategories); } +#ifndef Q_OS_WIN32 +void Settings::saveInhibitSuspend(bool v) +{ + SET_VALUE_MOD(inhibitSuspend); +} +#endif + void Settings::save(bool force) { if (force) { diff --git a/gui/settings.h b/gui/settings.h index bcbd58dfa..28b276e25 100644 --- a/gui/settings.h +++ b/gui/settings.h @@ -172,6 +172,9 @@ public: bool monoSidebarIcons(); bool showTimeRemaining(); QStringList hiddenStreamCategories(); + #ifndef Q_OS_WIN32 + bool inhibitSuspend(); + #endif void removeConnectionDetails(const QString &v); void saveConnectionDetails(const MPDConnectionDetails &v); @@ -253,6 +256,9 @@ public: void saveMonoSidebarIcons(bool v); void saveShowTimeRemaining(bool v); void saveHiddenStreamCategories(const QStringList &v); + #ifndef Q_OS_WIN32 + void saveInhibitSuspend(bool v); + #endif void save(bool force=false); #ifdef ENABLE_KDE_SUPPORT bool openWallet(); diff --git a/mpd/mpdconnection.cpp b/mpd/mpdconnection.cpp index 68896c51b..f91d0b1a4 100644 --- a/mpd/mpdconnection.cpp +++ b/mpd/mpdconnection.cpp @@ -38,7 +38,9 @@ #include "thread.h" #include "settings.h" #include "cuefile.h" - +#ifndef Q_OS_WIN32 +#include "powermanagement.h" +#endif #include static bool debugEnabled=false; #define DBUG if (debugEnabled) qWarning() << "MPDConnection" << QThread::currentThreadId() @@ -181,6 +183,9 @@ MPDConnection::MPDConnection() qRegisterMetaType("MPDStatsValues"); qRegisterMetaType("MPDStatusValues"); qRegisterMetaType("MPDConnectionDetails"); + #ifndef Q_OS_WIN32 + connect(PowerManagement::self(), SIGNAL(resuming()), this, SLOT(reconnect())); + #endif } MPDConnection::~MPDConnection() diff --git a/mpd/mpdstatus.cpp b/mpd/mpdstatus.cpp index e2898c64c..0aca9e710 100644 --- a/mpd/mpdstatus.cpp +++ b/mpd/mpdstatus.cpp @@ -26,12 +26,33 @@ #include "mpdstatus.h" #include "mpdconnection.h" +#ifndef Q_OS_WIN32 +#include "powermanagement.h" +#include "localize.h" +#endif MPDStatus * MPDStatus::self() { static MPDStatus instance; return &instance; } +#ifndef Q_OS_WIN32 +static bool inhibitSuspendWhilstPlaying=false; +bool MPDStatus::inhibitSuspend() +{ + return inhibitSuspendWhilstPlaying; +} + +void MPDStatus::setInhibitSuspend(bool i) +{ + if (i!=inhibitSuspendWhilstPlaying) { + inhibitSuspendWhilstPlaying=i; + if (!inhibitSuspendWhilstPlaying) { + PowerManagement::self()->stopSuppressingSleep(); + } + } +} +#endif MPDStatus::MPDStatus() { @@ -40,6 +61,15 @@ MPDStatus::MPDStatus() void MPDStatus::update(const MPDStatusValues &v) { + #ifndef Q_OS_WIN32 + if (inhibitSuspendWhilstPlaying) { + if (MPDState_Playing==v.state) { + PowerManagement::self()->beginSuppressingSleep(i18n("Cantata is playing a track")); + } else { + PowerManagement::self()->stopSuppressingSleep(); + } + } + #endif values=v; emit updated(); } diff --git a/mpd/mpdstatus.h b/mpd/mpdstatus.h index fa7f7cbad..689b96e06 100644 --- a/mpd/mpdstatus.h +++ b/mpd/mpdstatus.h @@ -91,6 +91,10 @@ public: ~MPDStatus() {} static MPDStatus * self(); + #ifndef Q_OS_WIN32 + static bool inhibitSuspend(); + static void setInhibitSuspend(bool i); + #endif // NOTE: There are no read/write locks aroud these values as they are read/written only fro the GUI thread... qint8 volume() const { return values.volume; }