From c9e979626f9b22d2c1509cfe006b6bc351a1b1c3 Mon Sep 17 00:00:00 2001
From: Lawrence Rust <lvr@softsystem.co.uk>
Date: Tue, 19 Apr 2011 10:12:45 +0200
Subject: [PATCH] Wait in MediaMonitorUnix until UDisks service is available
When booting up, MythTV can start in parallel with DBus. However, the UDisks
service is started asynchroously by DBus and isn't available immediately.
This change makes CheckMountable poll for the UDisks service, which is needed
to enumerate CD/DVD drives and other hot plug drives.
Signed-off-by: Lawrence Rust <lvr@softsystem.co.uk>
---
mythtv/libs/libmyth/mediamonitor-unix.cpp | 107 ++++++++++++++++-------------
1 files changed, 58 insertions(+), 49 deletions(-)
diff --git a/mythtv/libs/libmyth/mediamonitor-unix.cpp b/mythtv/libs/libmyth/mediamonitor-unix.cpp
index ffb4480..c202b74 100644
a
|
b
|
static QVariant DeviceProperty(const QDBusObjectPath& o, const char kszProperty[ |
185 | 185 | bool MediaMonitorUnix::CheckMountable(void) |
186 | 186 | { |
187 | 187 | #if CONFIG_QTDBUS |
188 | | // Listen on DBus for UDisk add/remove device messages |
189 | | QDBusConnection::systemBus().connect( |
190 | | UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, UDISKS_DEVADD, UDISKS_DEVSIG, |
191 | | this, SLOT(deviceAdded(QDBusObjectPath)) ); |
192 | | QDBusConnection::systemBus().connect( |
193 | | UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, UDISKS_DEVRMV, UDISKS_DEVSIG, |
194 | | this, SLOT(deviceRemoved(QDBusObjectPath)) ); |
195 | | |
196 | | // Connect to UDisks |
197 | | QDBusInterface iface(UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, |
198 | | QDBusConnection::systemBus() ); |
199 | | if (!iface.isValid()) |
| 188 | for (int i = 0; i < 10; ++i, usleep(500000)) |
200 | 189 | { |
201 | | LOG(VB_GENERAL, LOG_ALERT, LOC + |
202 | | "CheckMountable: DBus interface error: " + |
203 | | iface.lastError().message() ); |
204 | | return false; |
205 | | } |
| 190 | // Connect to UDisks. This can sometimes fail if mythfrontend |
| 191 | // is started during system init |
| 192 | QDBusInterface iface(UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, |
| 193 | QDBusConnection::systemBus() ); |
| 194 | if (!iface.isValid()) |
| 195 | { |
| 196 | LOG(VB_GENERAL, LOG_ALERT, LOC + |
| 197 | "CheckMountable: DBus interface error: " + |
| 198 | iface.lastError().message() ); |
| 199 | continue; |
| 200 | } |
206 | 201 | |
207 | | // Enumerate devices |
208 | | typedef QList<QDBusObjectPath> QDBusObjectPathList; |
209 | | QDBusReply<QDBusObjectPathList> reply = iface.call("EnumerateDevices"); |
210 | | if (!reply.isValid()) |
211 | | { |
212 | | LOG(VB_GENERAL, LOG_ALERT, LOC + |
213 | | "CheckMountable DBus EnumerateDevices error: " + |
214 | | reply.error().message() ); |
215 | | return false; |
216 | | } |
| 202 | // Enumerate devices |
| 203 | typedef QList<QDBusObjectPath> QDBusObjectPathList; |
| 204 | QDBusReply<QDBusObjectPathList> reply = iface.call("EnumerateDevices"); |
| 205 | if (!reply.isValid()) |
| 206 | { |
| 207 | LOG(VB_GENERAL, LOG_ALERT, LOC + |
| 208 | "CheckMountable DBus EnumerateDevices error: " + |
| 209 | reply.error().message() ); |
| 210 | continue; |
| 211 | } |
217 | 212 | |
218 | | // Parse the returned device array |
219 | | const QDBusObjectPathList& list(reply.value()); |
220 | | for (QDBusObjectPathList::const_iterator it = list.begin(); |
221 | | it != list.end(); ++it) |
222 | | { |
223 | | if (!DeviceProperty(*it, "DeviceIsSystemInternal").toBool() && |
224 | | !DeviceProperty(*it, "DeviceIsPartitionTable").toBool() ) |
| 213 | // Listen on DBus for UDisk add/remove device messages |
| 214 | (void)QDBusConnection::systemBus().connect( |
| 215 | UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, UDISKS_DEVADD, UDISKS_DEVSIG, |
| 216 | this, SLOT(deviceAdded(QDBusObjectPath)) ); |
| 217 | (void)QDBusConnection::systemBus().connect( |
| 218 | UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, UDISKS_DEVRMV, UDISKS_DEVSIG, |
| 219 | this, SLOT(deviceRemoved(QDBusObjectPath)) ); |
| 220 | |
| 221 | // Parse the returned device array |
| 222 | const QDBusObjectPathList& list(reply.value()); |
| 223 | for (QDBusObjectPathList::const_iterator it = list.begin(); |
| 224 | it != list.end(); ++it) |
225 | 225 | { |
226 | | QString dev = DeviceProperty(*it, "DeviceFile").toString(); |
| 226 | if (!DeviceProperty(*it, "DeviceIsSystemInternal").toBool() && |
| 227 | !DeviceProperty(*it, "DeviceIsPartitionTable").toBool() ) |
| 228 | { |
| 229 | QString dev = DeviceProperty(*it, "DeviceFile").toString(); |
227 | 230 | |
228 | | // ignore floppies, too slow |
229 | | if (dev.startsWith("/dev/fd")) |
230 | | continue; |
| 231 | // ignore floppies, too slow |
| 232 | if (dev.startsWith("/dev/fd")) |
| 233 | continue; |
231 | 234 | |
232 | | MythMediaDevice* pDevice; |
233 | | if (DeviceProperty(*it, "DeviceIsRemovable").toBool()) |
234 | | pDevice = MythCDROM::get(this, dev.toAscii(), false, m_AllowEject); |
235 | | else |
236 | | pDevice = MythHDD::Get(this, dev.toAscii(), false, false); |
| 235 | MythMediaDevice* pDevice; |
| 236 | if (DeviceProperty(*it, "DeviceIsRemovable").toBool()) |
| 237 | pDevice = MythCDROM::get(this, dev.toAscii(), false, m_AllowEject); |
| 238 | else |
| 239 | pDevice = MythHDD::Get(this, dev.toAscii(), false, false); |
237 | 240 | |
238 | | if (pDevice && !AddDevice(pDevice)) |
239 | | pDevice->deleteLater(); |
| 241 | if (pDevice && !AddDevice(pDevice)) |
| 242 | pDevice->deleteLater(); |
| 243 | } |
240 | 244 | } |
| 245 | |
| 246 | // Success |
| 247 | return true; |
241 | 248 | } |
242 | | return true; |
| 249 | |
| 250 | // Timed out |
| 251 | return false; |
243 | 252 | |
244 | 253 | #elif defined linux |
245 | 254 | // NB needs script in /etc/udev/rules.d |