1 /*
2     SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
3     SPDX-License-Identifier: GPL-2.0-or-later
4 */
5 
6 #ifndef _K3B_DEVICE_HANDLER_H_
7 #define _K3B_DEVICE_HANDLER_H_
8 
9 #include "k3bthreadjob.h"
10 #include "k3bdevice.h"
11 #include "k3bdiskinfo.h"
12 #include "k3bmsf.h"
13 #include "k3bcdtext.h"
14 #include "k3b_export.h"
15 
16 
17 namespace K3b {
18     namespace Device
19     {
20         class Device;
21 
22         /**
23          * The Device::Devicehandler is a threaded wrapper around Device::Device.
24          * It allows async access to the time consuming blocking Device::Device methods.
25          * Since it's a Job it is very easy to handle. Just use one of the methods and
26          * connect to the finished signal.
27          * Be aware that all methods only return valid values if the corresponding info has
28          * been successfully requested.
29          *
30          * Be aware that multiple requests in a row (without waiting for the job to finish) will
31          * only result in one finished() signal answering the last request.
32          */
33         class LIBK3B_EXPORT DeviceHandler : public ThreadJob
34         {
35             Q_OBJECT
36 
37         public:
38             enum Command {
39                 CommandNone = 0x0,
40 
41                 /**
42                  * Retrieve basic disk information.
43                  * Always successful, even with an empty or no media at all!
44                  *
45                  * \sa diskInfo()
46                  */
47                 CommandDiskInfo = 0x1,
48 
49                 /**
50                  * Retrieve the Toc.
51                  * Always successful, even with an empty or no media at all!
52                  *
53                  * \sa toc()
54                  */
55                 CommandToc = 0x2,
56 
57                 /**
58                  * Retrieve the CD-Text.
59                  *
60                  * Successful if the media contains CD-Text.
61                  *
62                  * \sa cdText()
63                  */
64                 CommandCdText = 0x4,
65 
66                 /**
67                  * Retrieve the raw, undecoded CD-Text.
68                  *
69                  * Successful if the media contains CD-Text.
70                  *
71                  * \sa rawCdText()
72                  */
73                 CommandCdTextRaw = 0x8,
74 
75                 /**
76                  * Retrieve the size of the disk.
77                  *
78                  * Always successful, even with an empty or no media at all!
79                  *
80                  * \sa diskSize()
81                  */
82                 CommandDiskSize = 0x10,
83 
84                 /**
85                  * Retrieve the remaining size of the disk.
86                  *
87                  * Always successful, even with an empty or no media at all!
88                  *
89                  * \sa remainingSize()
90                  */
91                 CommandRemainingSize = 0x20,
92 
93                 /**
94                  * Always successful, even with an empty or no media at all!
95                  */
96                 CommandTocType = 0x40,
97 
98                 /**
99                  * Always successful, even with an empty or no media at all!
100                  */
101                 CommandNumSessions = 0x80,
102 
103                 /**
104                  * Successful if the drive could be blocked.
105                  */
106                 CommandBlock = 0x100,
107 
108                 /**
109                  * Successful if the drive could be unblocked.
110                  */
111                 CommandUnblock = 0x200,
112 
113                 /**
114                  * Successful if the media was ejected.
115                  */
116                 CommandEject = 0x400,
117 
118                 /**
119                  * Successful if the media was loaded
120                  */
121                 CommandLoad = 0x800,
122 
123                 CommandReload = CommandEject|CommandLoad,
124 
125                 /**
126                  * Determine the device buffer state.
127                  */
128                 CommandBufferCapacity = 0x1000,
129 
130                 CommandNextWritableAddress = 0x2000,
131 
132                 /**
133                  * Retrieves all medium information: CommandDiskInfo, CommandToc, and CommandCdText in case of an audio or mixed
134                  * mode cd.
135                  *
136                  * Always successful, even with an empty or no media at all!
137                  *
138                  * \sa diskInfo(), toc(), cdText()
139                  */
140                 CommandMediaInfo = CommandDiskInfo|CommandToc|CommandCdText
141             };
142             Q_DECLARE_FLAGS( Commands, Command )
143 
144             DeviceHandler( Device*, QObject* parent = 0 );
145             DeviceHandler( QObject* parent = 0 );
146 
147             /**
148              * This constructor is used by the global "quick" methods and should not be used
149              * otherwise except for the same usage.
150              */
151             DeviceHandler( Commands command, Device* );
152 
153             ~DeviceHandler() override;
154 
155             DiskInfo diskInfo() const;
156             Toc toc() const;
157             CdText cdText() const;
158             QByteArray cdTextRaw() const;
159             Msf diskSize() const;
160             Msf remainingSize() const;
161             int tocType() const;
162             int numSessions() const;
163             long long bufferCapacity() const;
164             long long availableBufferCapacity() const;
165 
166             Msf nextWritableAddress() const;
167 
168             bool success() const;
169 
170         Q_SIGNALS:
171             void finished( K3b::Device::DeviceHandler* );
172 
173         public Q_SLOTS:
174             void setDevice( K3b::Device::Device* );
175             void sendCommand( Commands command );
176 
177             void getToc();
178             void getDiskInfo();
179             void getDiskSize();
180             void getRemainingSize();
181             void getTocType();
182             void getNumSessions();
183             void block( bool );
184             void eject();
185 
186         private:
187             void jobFinished( bool success ) override;
188             bool run() override;
189 
190             class Private;
191             Private* const d;
192         };
193 
194         /**
195          * Usage:
196          * \code
197          *  connect( Device::sendCommand( Device::DeviceHandler::CommandDiskInfo, dev ),
198          *           SIGNAL(finished(DeviceHandler*)),
199          *           this, SLOT(someSlot(DeviceHandler*)) );
200          *
201          *  void someSlot( DeviceHandler* dh ) {
202          *     if( dh->success() ) {
203          * \endcode
204          *
205          * Be aware that the DeviceHandler will get destroyed once the signal has been
206          * emitted.
207          */
208         LIBK3B_EXPORT DeviceHandler* sendCommand( DeviceHandler::Commands command, Device* );
209 
mediaInfo(Device * dev)210         inline DeviceHandler* mediaInfo(Device* dev) {
211             return sendCommand(DeviceHandler::CommandMediaInfo,dev);
212         }
213 
toc(Device * dev)214         inline DeviceHandler* toc(Device* dev) {
215             return sendCommand(DeviceHandler::CommandToc,dev);
216         }
217 
diskSize(Device * dev)218         inline DeviceHandler* diskSize(Device* dev) {
219             return sendCommand(DeviceHandler::CommandDiskSize,dev);
220         }
221 
remainingSize(Device * dev)222         inline DeviceHandler* remainingSize(Device* dev) {
223             return sendCommand(DeviceHandler::CommandRemainingSize,dev);
224         }
225 
tocType(Device * dev)226         inline DeviceHandler* tocType(Device* dev) {
227             return sendCommand(DeviceHandler::CommandTocType,dev);
228         }
229 
numSessions(Device * dev)230         inline DeviceHandler* numSessions(Device* dev) {
231             return sendCommand(DeviceHandler::CommandNumSessions,dev);
232         }
233 
block(Device * dev)234         inline DeviceHandler* block(Device* dev) {
235             return sendCommand(DeviceHandler::CommandBlock,dev);
236         }
237 
unblock(Device * dev)238         inline DeviceHandler* unblock(Device* dev) {
239             return sendCommand(DeviceHandler::CommandUnblock,dev);
240         }
241 
eject(Device * dev)242         inline DeviceHandler* eject(Device* dev) {
243             return sendCommand(DeviceHandler::CommandEject,dev);
244         }
245 
reload(Device * dev)246         inline DeviceHandler* reload(Device* dev) {
247             return sendCommand(DeviceHandler::CommandReload,dev);
248         }
249 
load(Device * dev)250         inline DeviceHandler* load(Device* dev) {
251             return sendCommand(DeviceHandler::CommandLoad,dev);
252         }
253     }
254 }
255 
256 Q_DECLARE_OPERATORS_FOR_FLAGS(K3b::Device::DeviceHandler::Commands)
257 
258 LIBK3B_EXPORT QDebug operator<<( QDebug dbg, K3b::Device::DeviceHandler::Commands commands );
259 
260 #endif
261