MythTV master
mythscreensaverdbus.cpp
Go to the documentation of this file.
1// Qt
2#include <QDBusConnection>
3#include <QDBusInterface>
4#include <QDBusReply>
5#include <QString>
6
7// MythTV
10
11// Std
12#include <array>
13#include <cstdint>
14#include <string>
15
16#define LOC QString("ScreenSaverDBus: ")
17
18const std::string kApp = "MythTV";
19const std::string kReason = "Watching TV";
20const std::string kDbusInhibit = "Inhibit";
21
22static constexpr size_t NUM_DBUS_METHODS { 4 };
23// Thanks to vlc for the set of dbus services to use.
24const std::array<const QString,NUM_DBUS_METHODS> kDbusService {
25 "org.freedesktop.ScreenSaver",
26 "org.freedesktop.PowerManagement.Inhibit",
27 "org.mate.SessionManager",
28 "org.gnome.SessionManager",
29};
30
31const std::array<const QString,NUM_DBUS_METHODS> kDbusPath {
32 "/ScreenSaver",
33 "/org/freedesktop/PowerManagement",
34 "/org/mate/SessionManager",
35 "/org/gnome/SessionManager",
36};
37
38// Service name is also the interface name in all cases
39
40const std::array<const QString,NUM_DBUS_METHODS> kDbusUnInhibit {
41 "UnInhibit",
42 "UnInhibit",
43 "Uninhibit",
44 "Uninhibit",
45};
46
48{
49 friend class MythScreenSaverDBus;
50
51 public:
52 ScreenSaverDBusPrivate(const QString &dbusService, const QString& dbusPath,
53 const QString &dbusInterface, QDBusConnection *bus)
54 : m_bus(bus),
55 m_interface(new QDBusInterface(dbusService, dbusPath , dbusInterface, *m_bus)),
56 m_serviceUsed(dbusService)
57 {
58 if (!m_interface->isValid())
59 {
60 LOG(VB_GENERAL, LOG_DEBUG, LOC +
61 QString("Could not connect to dbus service %1: %2")
62 .arg(dbusService, m_interface->lastError().message()));
63 }
64 else
65 {
66 LOG(VB_GENERAL, LOG_INFO, LOC + "Created for DBus service: " + dbusService);
67 }
68 }
70 {
71 delete m_interface;
72 }
73 void Inhibit(QString* errout = nullptr)
74 {
75 if (m_interface->isValid())
76 {
77 // method uint org.freedesktop.ScreenSaver.Inhibit(QString application_name, QString reason_for_inhibit)
78 QDBusMessage msg = m_interface->call(QDBus::Block,
79 kDbusInhibit.c_str(),
80 kApp.c_str(), kReason.c_str());
81 if (msg.type() == QDBusMessage::ReplyMessage)
82 {
83 QList<QVariant> replylist = msg.arguments();
84 const QVariant& reply = replylist.first();
85 m_cookie = reply.toUInt();
86 LOG(VB_GENERAL, LOG_INFO, LOC +
87 QString("Successfully inhibited screensaver via %1. cookie %2. nom nom")
88 .arg(m_serviceUsed).arg(m_cookie));
89 return;
90 }
91
92 // msg.type() == QDBusMessage::ErrorMessage
93 if (errout != nullptr)
94 {
95 *errout = msg.errorMessage();
96 }
97 else
98 {
99 LOG(VB_GENERAL, LOG_WARNING, LOC +
100 QString("Failed to disable screensaver via %1: %2")
101 .arg(m_serviceUsed, msg.errorMessage()));
102 }
103 }
104 }
106 {
107 if (m_interface->isValid())
108 {
109 // Don't block waiting for the reply, there isn't one
110 // method void org.freedesktop.ScreenSaver.UnInhibit(uint cookie) (or equivalent)
111 if (m_cookie != 0) {
112 m_interface->call(QDBus::NoBlock, m_unInhibit , m_cookie);
113 m_cookie = 0;
114 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screensaver uninhibited via %1")
115 .arg(m_serviceUsed));
116 }
117 }
118 }
119 void SetUnInhibit(const QString &method) { m_unInhibit = method; }
120 bool isValid() const { return m_interface ? m_interface->isValid() : false; };
121
122 protected:
123 uint32_t m_cookie {0};
124 QDBusConnection *m_bus {nullptr};
125 QDBusInterface *m_interface {nullptr};
126 private:
127 // Disable copying and assignment
128 Q_DISABLE_COPY(ScreenSaverDBusPrivate)
129 QString m_unInhibit;
131};
132
134 : MythScreenSaver(Parent),
135 m_bus(QDBusConnection::sessionBus())
136{
137 // service, path, interface, bus - note that interface = service, hence it is used twice
138 for (size_t i=0; i < NUM_DBUS_METHODS; i++)
139 {
140 auto *ssdbp = new ScreenSaverDBusPrivate(kDbusService[i], kDbusPath[i], kDbusService[i], &m_bus);
141 if (!ssdbp->isValid())
142 {
143 delete ssdbp;
144 continue;
145 }
146 ssdbp->SetUnInhibit(kDbusUnInhibit[i]);
147
148 // Possible control. Does it work without error?
149 QString dbuserr;
150 ssdbp->Inhibit(&dbuserr);
151 ssdbp->UnInhibit();
152 if (!dbuserr.isEmpty())
153 {
154 LOG(VB_GENERAL, LOG_DEBUG, LOC +
155 QString("Error testing disable screensaver via %1: %2")
156 .arg(kDbusService[i], dbuserr));
157 delete ssdbp;
158 continue;
159 }
160 m_dbusPrivateInterfaces.push_back(ssdbp);
161 }
162}
163
165{
167 for (auto * interface : std::as_const(m_dbusPrivateInterfaces))
168 delete interface;
169}
170
172{
173 for (auto * interface : std::as_const(m_dbusPrivateInterfaces))
174 interface->Inhibit();
175}
176
178{
179 for (auto * interface : std::as_const(m_dbusPrivateInterfaces))
180 interface->UnInhibit();
181}
182
184{
185}
186
188{
189 return false;
190}
QList< ScreenSaverDBusPrivate * > m_dbusPrivateInterfaces
Base Class for screensavers.
void SetUnInhibit(const QString &method)
void Inhibit(QString *errout=nullptr)
ScreenSaverDBusPrivate(const QString &dbusService, const QString &dbusPath, const QString &dbusInterface, QDBusConnection *bus)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
const std::string kReason
const std::array< const QString, NUM_DBUS_METHODS > kDbusPath
const std::array< const QString, NUM_DBUS_METHODS > kDbusService
KDE >= 4 and GNOME >= 3.10.
const std::string kDbusInhibit
const std::string kApp
const std::array< const QString, NUM_DBUS_METHODS > kDbusUnInhibit
static constexpr size_t NUM_DBUS_METHODS