1 /*
2 Copyright 2006 Kevin Ottens <ervin@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), which shall
10 act as a proxy defined in Section 6 of version 3 of the license.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "halcdrom.h"
22
23 #include <QtCore/QStringList>
24 #include <QtDBus/QDBusInterface>
25 #include <QtDBus/QDBusReply>
26 #include <QtDBus/QDBusError>
27 #include <QtDBus/QDBusVariant>
28
29 #include "halfstabhandling.h"
30
31 using namespace Solid::Backends::Hal;
32
Cdrom(HalDevice * device)33 Cdrom::Cdrom(HalDevice *device)
34 : Storage(device), m_ejectInProgress(false)
35 {
36 connect(device, SIGNAL(conditionRaised(QString,QString)),
37 this, SLOT(slotCondition(QString,QString)));
38 m_device->registerAction("eject", this,
39 SLOT(slotEjectRequested()),
40 SLOT(slotEjectDone(int,QString)));
41 }
42
~Cdrom()43 Cdrom::~Cdrom()
44 {
45
46 }
47
48
supportedMedia() const49 Solid::OpticalDrive::MediumTypes Cdrom::supportedMedia() const
50 {
51 Solid::OpticalDrive::MediumTypes supported;
52
53 QMap<Solid::OpticalDrive::MediumType, QString> map;
54 map[Solid::OpticalDrive::Cdr] = "storage.cdrom.cdr";
55 map[Solid::OpticalDrive::Cdrw] = "storage.cdrom.cdrw";
56 map[Solid::OpticalDrive::Dvd] = "storage.cdrom.dvd";
57 map[Solid::OpticalDrive::Dvdr] = "storage.cdrom.dvdr";
58 map[Solid::OpticalDrive::Dvdrw] ="storage.cdrom.dvdrw";
59 map[Solid::OpticalDrive::Dvdram] ="storage.cdrom.dvdram";
60 map[Solid::OpticalDrive::Dvdplusr] ="storage.cdrom.dvdplusr";
61 map[Solid::OpticalDrive::Dvdplusrw] ="storage.cdrom.dvdplusrw";
62 map[Solid::OpticalDrive::Dvdplusdl] ="storage.cdrom.dvdplusrdl";
63 map[Solid::OpticalDrive::Dvdplusdlrw] ="storage.cdrom.dvdplusrwdl";
64 map[Solid::OpticalDrive::Bd] ="storage.cdrom.bd";
65 map[Solid::OpticalDrive::Bdr] ="storage.cdrom.bdr";
66 map[Solid::OpticalDrive::Bdre] ="storage.cdrom.bdre";
67 map[Solid::OpticalDrive::HdDvd] ="storage.cdrom.hddvd";
68 map[Solid::OpticalDrive::HdDvdr] ="storage.cdrom.hddvdr";
69 map[Solid::OpticalDrive::HdDvdrw] ="storage.cdrom.hddvdrw";
70
71 foreach (const Solid::OpticalDrive::MediumType type, map.keys())
72 {
73 if (m_device->prop(map[type]).toBool())
74 {
75 supported|= type;
76 }
77 }
78
79 return supported;
80 }
81
readSpeed() const82 int Cdrom::readSpeed() const
83 {
84 return m_device->prop("storage.cdrom.read_speed").toInt();
85 }
86
writeSpeed() const87 int Cdrom::writeSpeed() const
88 {
89 return m_device->prop("storage.cdrom.write_speed").toInt();
90 }
91
writeSpeeds() const92 QList<int> Cdrom::writeSpeeds() const
93 {
94 QList<int> speeds;
95 QStringList speed_strlist = m_device->prop("storage.cdrom.write_speeds").toStringList();
96
97 foreach (const QString &speed_str, speed_strlist)
98 {
99 speeds << speed_str.toInt();
100 }
101
102 return speeds;
103 }
104
slotCondition(const QString & name,const QString &)105 void Cdrom::slotCondition(const QString &name, const QString &/*reason */)
106 {
107 if (name == "EjectPressed")
108 {
109 emit ejectPressed(m_device->udi());
110 }
111 }
112
eject()113 bool Cdrom::eject()
114 {
115 if (m_ejectInProgress) {
116 return false;
117 }
118 m_ejectInProgress = true;
119 m_device->broadcastActionRequested("eject");
120
121 if (FstabHandling::isInFstab(m_device->prop("block.device").toString())) {
122 return callSystemEject();
123 } else {
124 return callHalDriveEject();
125 }
126 }
127
slotEjectRequested()128 void Cdrom::slotEjectRequested()
129 {
130 m_ejectInProgress = true;
131 emit ejectRequested(m_device->udi());
132 }
133
callHalDriveEject()134 bool Cdrom::callHalDriveEject()
135 {
136 QString udi = m_device->udi();
137 QString interface = "org.freedesktop.Hal.Device.Storage";
138
139 // HACK: Eject doesn't work on cdrom drives when there's a mounted disc,
140 // let's try to workaround this by calling a child volume...
141 if (m_device->prop("storage.removable.media_available").toBool()) {
142 QDBusInterface manager("org.freedesktop.Hal",
143 "/org/freedesktop/Hal/Manager",
144 "org.freedesktop.Hal.Manager",
145 QDBusConnection::systemBus());
146
147 QDBusReply<QStringList> reply = manager.call("FindDeviceStringMatch", "info.parent", udi);
148
149 if (reply.isValid())
150 {
151 const QStringList udis = reply;
152 if (!udis.isEmpty()) {
153 udi = udis[0];
154 interface = "org.freedesktop.Hal.Device.Volume";
155 }
156 }
157 }
158
159 QDBusConnection c = QDBusConnection::systemBus();
160 QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi,
161 interface, "Eject");
162
163 msg << QStringList();
164
165
166 return c.callWithCallback(msg, this,
167 SLOT(slotDBusReply(QDBusMessage)),
168 SLOT(slotDBusError(QDBusError)));
169 }
170
callSystemEject()171 bool Solid::Backends::Hal::Cdrom::callSystemEject()
172 {
173 const QString device = m_device->prop("block.device").toString();
174 m_process = FstabHandling::callSystemCommand("eject", device,
175 this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
176
177 return m_process!=nullptr;
178 }
179
slotDBusReply(const QDBusMessage &)180 void Cdrom::slotDBusReply(const QDBusMessage &/*reply*/)
181 {
182 m_ejectInProgress = false;
183 m_device->broadcastActionDone("eject");
184 }
185
slotDBusError(const QDBusError & error)186 void Cdrom::slotDBusError(const QDBusError &error)
187 {
188 m_ejectInProgress = false;
189
190 // TODO: Better error reporting here
191 m_device->broadcastActionDone("eject", Solid::UnauthorizedOperation,
192 QString(error.name()+": "+error.message()));
193 }
194
slotProcessFinished(int exitCode,QProcess::ExitStatus exitStatus)195 void Solid::Backends::Hal::Cdrom::slotProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
196 {
197 Q_UNUSED(exitStatus);
198 if (m_ejectInProgress) {
199 m_ejectInProgress = false;
200
201 if (exitCode==0) {
202 m_device->broadcastActionDone("eject");
203 } else {
204 m_device->broadcastActionDone("eject", Solid::UnauthorizedOperation,
205 m_process->readAllStandardError());
206 }
207 }
208
209 delete m_process;
210 }
211
slotEjectDone(int error,const QString & errorString)212 void Cdrom::slotEjectDone(int error, const QString &errorString)
213 {
214 m_ejectInProgress = false;
215 emit ejectDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
216 }
217
218 #include "backends/hal/moc_halcdrom.cpp"
219