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 
18 const std::string kApp = "MythTV";
19 const std::string kReason = "Watching TV";
20 const std::string kDbusInhibit = "Inhibit";
21 
22 static constexpr size_t NUM_DBUS_METHODS { 4 };
23 // Thanks to vlc for the set of dbus services to use.
24 const 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 
31 const 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 
40 const 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  QVariant reply = replylist.first();
85  m_cookie = reply.toUInt();
86  m_inhibited = true;
87  LOG(VB_GENERAL, LOG_INFO, LOC +
88  QString("Successfully inhibited screensaver via %1. cookie %2. nom nom")
89  .arg(m_serviceUsed).arg(m_cookie));
90  return;
91  }
92 
93  // msg.type() == QDBusMessage::ErrorMessage
94  if (errout != nullptr)
95  {
96  *errout = msg.errorMessage();
97  }
98  else
99  {
100  LOG(VB_GENERAL, LOG_WARNING, LOC +
101  QString("Failed to disable screensaver via %1: %2")
102  .arg(m_serviceUsed, msg.errorMessage()));
103  }
104  }
105  }
106  void UnInhibit()
107  {
108  if (m_interface->isValid())
109  {
110  // Don't block waiting for the reply, there isn't one
111  // method void org.freedesktop.ScreenSaver.UnInhibit(uint cookie) (or equivalent)
112  if (m_cookie != 0) {
113  m_interface->call(QDBus::NoBlock, m_unInhibit , m_cookie);
114  m_cookie = 0;
115  m_inhibited = false;
116  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Screensaver uninhibited via %1")
117  .arg(m_serviceUsed));
118  }
119  }
120  }
121  void SetUnInhibit(const QString &method) { m_unInhibit = method; }
122  bool isValid() const { return m_interface ? m_interface->isValid() : false; };
123 
124  protected:
125  bool m_inhibited {false};
126  uint32_t m_cookie {0};
127  QDBusConnection *m_bus {nullptr};
128  QDBusInterface *m_interface {nullptr};
129  private:
130  // Disable copying and assignment
131  Q_DISABLE_COPY(ScreenSaverDBusPrivate)
132  QString m_unInhibit;
133  QString m_serviceUsed;
134 };
135 
137  : MythScreenSaver(Parent),
138  m_bus(QDBusConnection::sessionBus())
139 {
140  // service, path, interface, bus - note that interface = service, hence it is used twice
141  for (size_t i=0; i < NUM_DBUS_METHODS; i++)
142  {
143  auto *ssdbp = new ScreenSaverDBusPrivate(kDbusService[i], kDbusPath[i], kDbusService[i], &m_bus);
144  if (!ssdbp->isValid())
145  {
146  delete ssdbp;
147  continue;
148  }
149  ssdbp->SetUnInhibit(kDbusUnInhibit[i]);
150 
151  // Possible control. Does it work without error?
152  QString dbuserr;
153  ssdbp->Inhibit(&dbuserr);
154  ssdbp->UnInhibit();
155  if (!dbuserr.isEmpty())
156  {
157  LOG(VB_GENERAL, LOG_DEBUG, LOC +
158  QString("Error testing disable screensaver via %1: %2")
159  .arg(kDbusService[i], dbuserr));
160  delete ssdbp;
161  continue;
162  }
163  m_dbusPrivateInterfaces.push_back(ssdbp);
164  }
165 }
166 
168 {
170  for (auto * interface : std::as_const(m_dbusPrivateInterfaces))
171  delete interface;
172 }
173 
175 {
176  for (auto * interface : std::as_const(m_dbusPrivateInterfaces))
177  interface->Inhibit();
178 }
179 
181 {
182  for (auto * interface : std::as_const(m_dbusPrivateInterfaces))
183  interface->UnInhibit();
184 }
185 
187 {
188 }
189 
191 {
192  return std::any_of(m_dbusPrivateInterfaces.cbegin(), m_dbusPrivateInterfaces.cend(),
193  [](auto * interface){ return interface->m_inhibited; } );
194 }
ScreenSaverDBusPrivate::m_inhibited
bool m_inhibited
Definition: mythscreensaverdbus.cpp:125
ScreenSaverDBusPrivate::m_unInhibit
QString m_unInhibit
Definition: mythscreensaverdbus.cpp:132
ScreenSaverDBusPrivate::m_serviceUsed
QString m_serviceUsed
Definition: mythscreensaverdbus.cpp:133
ScreenSaverDBusPrivate::SetUnInhibit
void SetUnInhibit(const QString &method)
Definition: mythscreensaverdbus.cpp:121
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
kDbusPath
const std::array< const QString, NUM_DBUS_METHODS > kDbusPath
Definition: mythscreensaverdbus.cpp:31
MythScreenSaver
Base Class for screensavers.
Definition: mythscreensaver.h:14
ScreenSaverDBusPrivate
Definition: mythscreensaverdbus.cpp:47
ScreenSaverDBusPrivate::ScreenSaverDBusPrivate
ScreenSaverDBusPrivate(const QString &dbusService, const QString &dbusPath, const QString &dbusInterface, QDBusConnection *bus)
Definition: mythscreensaverdbus.cpp:52
MythScreenSaverDBus::Asleep
bool Asleep() override
Definition: mythscreensaverdbus.cpp:190
ScreenSaverDBusPrivate::Inhibit
void Inhibit(QString *errout=nullptr)
Definition: mythscreensaverdbus.cpp:73
mythscreensaverdbus.h
MythScreenSaverDBus::~MythScreenSaverDBus
~MythScreenSaverDBus() override
Definition: mythscreensaverdbus.cpp:167
mythlogging.h
ScreenSaverDBusPrivate::UnInhibit
void UnInhibit()
Definition: mythscreensaverdbus.cpp:106
MythScreenSaverDBus::Reset
void Reset() override
Definition: mythscreensaverdbus.cpp:186
ScreenSaverDBusPrivate::m_cookie
uint32_t m_cookie
Definition: mythscreensaverdbus.cpp:126
MythScreenSaverDBus::Disable
void Disable() override
Definition: mythscreensaverdbus.cpp:174
MythScreenSaverDBus
Definition: mythscreensaverdbus.h:10
MythScreenSaverDBus::Restore
void Restore() override
Definition: mythscreensaverdbus.cpp:180
MythScreenSaverDBus::m_dbusPrivateInterfaces
QList< ScreenSaverDBusPrivate * > m_dbusPrivateInterfaces
Definition: mythscreensaverdbus.h:27
kDbusService
const std::array< const QString, NUM_DBUS_METHODS > kDbusService
KDE >= 4 and GNOME >= 3.10.
Definition: mythscreensaverdbus.cpp:24
ScreenSaverDBusPrivate::m_interface
QDBusInterface * m_interface
Definition: mythscreensaverdbus.cpp:128
kReason
const std::string kReason
Definition: mythscreensaverdbus.cpp:19
LOC
#define LOC
Definition: mythscreensaverdbus.cpp:16
ScreenSaverDBusPrivate::isValid
bool isValid() const
Definition: mythscreensaverdbus.cpp:122
kApp
const std::string kApp
Definition: mythscreensaverdbus.cpp:18
ScreenSaverDBusPrivate::~ScreenSaverDBusPrivate
~ScreenSaverDBusPrivate()
Definition: mythscreensaverdbus.cpp:69
kDbusInhibit
const std::string kDbusInhibit
Definition: mythscreensaverdbus.cpp:20
kDbusUnInhibit
const std::array< const QString, NUM_DBUS_METHODS > kDbusUnInhibit
Definition: mythscreensaverdbus.cpp:40
NUM_DBUS_METHODS
static constexpr size_t NUM_DBUS_METHODS
Definition: mythscreensaverdbus.cpp:22
ScreenSaverDBusPrivate::m_bus
QDBusConnection * m_bus
Definition: mythscreensaverdbus.cpp:127