1
/****************************************************************************************
2
 * Copyright (c) 2008 Alejandro Wainzinger <aikawarazuni@gmail.com>                     *
3
 * Copyright (c) 2009 Nikolaj Hald Nielsen <nhn@kde.org>                                *
4
 *                                                                                      *
5
 * This program is free software; you can redistribute it and/or modify it under        *
6
 * the terms of the GNU General Public License as published by the Free Software        *
7
 * Foundation; either version 2 of the License, or (at your option) any later           *
8
 * version.                                                                             *
9
 *                                                                                      *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
11
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
12
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
13
 *                                                                                      *
14
 * You should have received a copy of the GNU General Public License along with         *
15
 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
16
 ****************************************************************************************/
17
18
#define DEBUG_PREFIX "MediaDeviceMonitor"
19
20
#include "MediaDeviceMonitor.h"
21
#include "ConnectionAssistant.h"
22
23
#include "core/support/Debug.h"
24
25
#include "MediaDeviceCache.h"
26
27
//solid specific includes
28
#include <solid/devicenotifier.h>
29
30
#include <solid/device.h>
31
#include <solid/opticaldisc.h>
32
#include <solid/storageaccess.h>
33
#include <solid/storagedrive.h>
34
#include <solid/portablemediaplayer.h>
35
#include <solid/opticaldrive.h>
36
37
#include <QTimer>
38
39
MediaDeviceMonitor* MediaDeviceMonitor::s_instance = 0;
40
41
MediaDeviceMonitor::MediaDeviceMonitor() : QObject()
42
 , m_udiAssistants()
43
 , m_assistants()
44
 , m_waitingassistants()
45
 , m_nextassistant( 0 )
46
 // NOTE: commented out, needs porting to new device framework
47
 //, m_currentCdId( QString() )
48
{
49
    DEBUG_BLOCK
50
    s_instance = this;
51
    init();
52
}
53
54
MediaDeviceMonitor::~MediaDeviceMonitor()
55
{
56
    s_instance = 0;
57
}
58
59
void
60
MediaDeviceMonitor::init()
61
{
62
    DEBUG_BLOCK
63
64
    // connect to device cache so new devices are tested too
65
    connect(  MediaDeviceCache::instance(),  SIGNAL(  deviceAdded( const QString& ) ),
66
              SLOT(  deviceAdded( const QString& ) ) );
67
    connect(  MediaDeviceCache::instance(),  SIGNAL(  deviceRemoved( const QString& ) ),
68
              SLOT(  slotDeviceRemoved( const QString& ) ) );
69
    connect(  MediaDeviceCache::instance(), SIGNAL( accessibilityChanged( bool, const QString & ) ),
70
              SLOT(  slotAccessibilityChanged( bool, const QString & ) ) );
71
}
72
73
QStringList
74
MediaDeviceMonitor::getDevices()
75
{
76
    DEBUG_BLOCK
77
    /* get list of devices */
78
    MediaDeviceCache::instance()->refreshCache();
79
    return MediaDeviceCache::instance()->getAll();
80
81
}
82
83
void MediaDeviceMonitor::checkDevice(const QString& udi)
84
{
85
    DEBUG_BLOCK
86
87
    // First let the higher priority devices check
88
89
    foreach( ConnectionAssistant* assistant, m_assistants )
90
    {
91
        checkOneDevice( assistant, udi );
92
    }
93
94
    // Then let the assistants that can wait check
95
96
    foreach( ConnectionAssistant* assistant, m_waitingassistants )
97
    {
98
        checkOneDevice( assistant, udi );
99
    }
100
101
}
102
103
void MediaDeviceMonitor::checkOneDevice( ConnectionAssistant* assistant, const QString& udi )
104
{
105
    // Ignore already identified devices
106
    if( m_udiAssistants.keys().contains( udi ) )
107
    {
108
        debug() << "Device already identified with udi: " << udi;
109
        return;
110
    }
111
112
    if( assistant->identify( udi ) )
113
    {
114
        debug() << "Device identified with udi: " << udi;
115
        // keep track of which assistant deals with which device
116
        m_udiAssistants.insert( udi, assistant );
117
        // inform factory of new device identified
118
        assistant->tellIdentified( udi );
119
        return;
120
    }
121
}
122
123
void MediaDeviceMonitor::checkDevicesFor( ConnectionAssistant* assistant )
124
{
125
    DEBUG_BLOCK
126
127
    QStringList udiList = getDevices();
128
129
    foreach( const QString &udi, udiList )
130
    {
131
        checkOneDevice( assistant, udi );
132
    }
133
134
}
135
136
void
137
MediaDeviceMonitor::registerDeviceType( ConnectionAssistant* assistant )
138
{
139
    DEBUG_BLOCK
140
141
    // If the device wants to wait and give other device types
142
    // a chance to recognize devices, put it in a queue for
143
    // later device checking
144
145
    if ( assistant->wait() )
146
    {
147
        // keep track of this type of device from now on
148
        m_waitingassistants << assistant;
149
150
        QTimer::singleShot( 1000, this, SLOT( slotDequeueWaitingAssistant() ) );
151
    }
152
    else
153
    {
154
        // keep track of this type of device from now on
155
        m_assistants << assistant;
156
157
        // start initial check for devices of this type
158
        checkDevicesFor( assistant );
159
    }
160
161
}
162
163
void
164
MediaDeviceMonitor::deviceAdded( const QString &udi )
165
{
166
    DEBUG_BLOCK
167
168
    // check if device is a known device
169
    checkDevice( udi );
170
}
171
172
void
173
MediaDeviceMonitor::slotDeviceRemoved( const QString &udi )
174
{
175
    DEBUG_BLOCK
176
177
    if ( m_udiAssistants.contains( udi ) )
178
    {
179
180
        m_udiAssistants.value( udi )->tellDisconnected( udi );
181
182
        m_udiAssistants.remove( udi );
183
    }
184
185
186
//    emit deviceRemoved( udi );
187
}
188
189
void
190
MediaDeviceMonitor::slotAccessibilityChanged( bool accessible, const QString & udi)
191
{
192
    // TODO: build a hack to force a device to become accessible or not
193
    // This means auto-mounting of Ipod, and ejecting of it too
194
195
    DEBUG_BLOCK
196
            debug() << "Accessibility changed to: " << ( accessible ? "true":"false" );
197
    if ( !accessible )
198
        deviceRemoved( udi );
199
    else
200
        deviceAdded( udi );
201
}
202
203
void
204
MediaDeviceMonitor::slotDequeueWaitingAssistant()
205
{
206
    checkDevicesFor( m_waitingassistants.at( m_nextassistant++ ) );
207
}
208
209
/// TODO: all stuff below here is cd-related, needs porting to new framework
210
#if 0
211
212
void
213
MediaDeviceMonitor::checkDevicesForCd()
214
{
215
    DEBUG_BLOCK
216
217
    QStringList udiList = getDevices();
218
219
    /* poll udi list for supported devices */
220
    foreach(const QString &udi, udiList )
221
    {
222
        debug() << "udi: " << udi;
223
        if ( isAudioCd( udi ) )
224
        {
225
            emit audioCdDetected( udi );
226
        }
227
    }
228
}
229
230
231
bool
232
MediaDeviceMonitor::isAudioCd( const QString & udi )
233
{
234
    DEBUG_BLOCK
235
236
    Solid::Device device;
237
238
    device = Solid::Device( udi );
239
    if( device.is<Solid::OpticalDisc>() )
240
    {
241
        debug() << "OpticalDisc";
242
        Solid::OpticalDisc * opt = device.as<Solid::OpticalDisc>();
243
        if ( opt->availableContent() & Solid::OpticalDisc::Audio )
244
        {
245
            debug() << "AudioCd";
246
            return true;
247
        }
248
    }
249
250
    return false;
251
}
252
253
QString
254
MediaDeviceMonitor::isCdPresent()
255
{
256
    DEBUG_BLOCK
257
258
    QStringList udiList = getDevices();
259
260
    /* poll udi list for supported devices */
261
    foreach( const QString &udi, udiList )
262
    {
263
        debug() << "udi: " << udi;
264
        if ( isAudioCd( udi ) )
265
        {
266
            return udi;
267
        }
268
    }
269
270
    return QString();
271
}
272
273
void
274
MediaDeviceMonitor::ejectCd( const QString & udi )
275
{
276
    DEBUG_BLOCK
277
    debug() << "trying to eject udi: " << udi;
278
    Solid::Device device = Solid::Device( udi ).parent();
279
280
    if ( !device.isValid() ) {
281
        debug() << "invalid device, cannot eject";
282
        return;
283
    }
284
285
286
    debug() << "lets tryto get an OpticalDrive out of this thing";
287
    if( device.is<Solid::OpticalDrive>() )
288
    {
289
        debug() << "claims to be an OpticalDrive";
290
        Solid::OpticalDrive * drive = device.as<Solid::OpticalDrive>();
291
        if ( drive )
292
        {
293
            debug() << "ejecting the bugger";
294
            drive->eject();
295
        }
296
    }
297
}
298
299
QString
300
MediaDeviceMonitor::currentCdId()
301
{
302
    return m_currentCdId;
303
}
304
305
void
306
MediaDeviceMonitor::setCurrentCdId( const QString & id )
307
{
308
    m_currentCdId = id;
309
}
310
311
312
#endif