File indexing completed on 2024-04-21 04:47:52

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Alejandro Wainzinger <aikawarazuni@gmail.com>                     *
0003  * Copyright (c) 2009 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0004  *                                                                                      *
0005  * This program is free software; you can redistribute it and/or modify it under        *
0006  * the terms of the GNU General Public License as published by the Free Software        *
0007  * Foundation; either version 2 of the License, or (at your option) any later           *
0008  * version.                                                                             *
0009  *                                                                                      *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0013  *                                                                                      *
0014  * You should have received a copy of the GNU General Public License along with         *
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0016  ****************************************************************************************/
0017 
0018 #define DEBUG_PREFIX "MediaDeviceMonitor"
0019 
0020 #include "MediaDeviceMonitor.h"
0021 
0022 #include "MediaDeviceCache.h"
0023 #include "core-impl/collections/mediadevicecollection/support/ConnectionAssistant.h"
0024 #include "core/support/Debug.h"
0025 
0026 #include <Solid/DeviceNotifier>
0027 #include <Solid/Device>
0028 #include <Solid/OpticalDisc>
0029 #include <Solid/StorageAccess>
0030 #include <Solid/StorageDrive>
0031 #include <Solid/PortableMediaPlayer>
0032 #include <Solid/OpticalDrive>
0033 
0034 #include <QTimer>
0035 
0036 MediaDeviceMonitor* MediaDeviceMonitor::s_instance = nullptr;
0037 
0038 MediaDeviceMonitor::MediaDeviceMonitor() : QObject()
0039  , m_udiAssistants()
0040  , m_assistants()
0041  , m_waitingassistants()
0042  , m_nextassistant( 0 )
0043  // NOTE: commented out, needs porting to new device framework
0044  //, m_currentCdId( QString() )
0045 {
0046     DEBUG_BLOCK
0047     s_instance = this;
0048     init();
0049 }
0050 
0051 MediaDeviceMonitor::~MediaDeviceMonitor()
0052 {
0053     s_instance = nullptr;
0054 }
0055 
0056 void
0057 MediaDeviceMonitor::init()
0058 {
0059     DEBUG_BLOCK
0060 
0061     // connect to device cache so new devices are tested too
0062     connect(  MediaDeviceCache::instance(),  &MediaDeviceCache::deviceAdded,
0063               this, &MediaDeviceMonitor::deviceAdded );
0064     connect(  MediaDeviceCache::instance(),  &MediaDeviceCache::deviceRemoved,
0065               this, &MediaDeviceMonitor::slotDeviceRemoved );
0066     connect(  MediaDeviceCache::instance(), &MediaDeviceCache::accessibilityChanged,
0067               this, &MediaDeviceMonitor::slotAccessibilityChanged );
0068 }
0069 
0070 QStringList
0071 MediaDeviceMonitor::getDevices()
0072 {
0073     DEBUG_BLOCK
0074     /* get list of devices */
0075     MediaDeviceCache::instance()->refreshCache();
0076     return MediaDeviceCache::instance()->getAll();
0077 
0078 }
0079 
0080 void MediaDeviceMonitor::checkDevice(const QString& udi)
0081 {
0082     DEBUG_BLOCK
0083 
0084     // First let the higher priority devices check
0085 
0086     foreach( ConnectionAssistant* assistant, m_assistants )
0087     {
0088         checkOneDevice( assistant, udi );
0089     }
0090 
0091     // Then let the assistants that can wait check
0092 
0093     foreach( ConnectionAssistant* assistant, m_waitingassistants )
0094     {
0095         checkOneDevice( assistant, udi );
0096     }
0097 
0098 }
0099 
0100 void MediaDeviceMonitor::checkOneDevice( ConnectionAssistant* assistant, const QString& udi )
0101 {
0102     // Ignore already identified devices
0103     if( m_udiAssistants.keys().contains( udi ) )
0104     {
0105         debug() << "Device already identified with udi: " << udi;
0106         return;
0107     }
0108 
0109     if( assistant->identify( udi ) )
0110     {
0111         debug() << "Device identified with udi: " << udi;
0112         // keep track of which assistant deals with which device
0113         m_udiAssistants.insert( udi, assistant );
0114         // inform factory of new device identified
0115         assistant->tellIdentified( udi );
0116         return;
0117     }
0118 }
0119 
0120 void MediaDeviceMonitor::checkDevicesFor( ConnectionAssistant* assistant )
0121 {
0122     DEBUG_BLOCK
0123 
0124     QStringList udiList = getDevices();
0125 
0126     foreach( const QString &udi, udiList )
0127     {
0128         checkOneDevice( assistant, udi );
0129     }
0130 
0131 }
0132 
0133 void
0134 MediaDeviceMonitor::registerDeviceType( ConnectionAssistant* assistant )
0135 {
0136     DEBUG_BLOCK
0137 
0138     // If the device wants to wait and give other device types
0139     // a chance to recognize devices, put it in a queue for
0140     // later device checking
0141 
0142     if ( assistant->wait() )
0143     {
0144         // keep track of this type of device from now on
0145         m_waitingassistants << assistant;
0146 
0147         QTimer::singleShot( 1000, this, &MediaDeviceMonitor::slotDequeueWaitingAssistant );
0148     }
0149     else
0150     {
0151         // keep track of this type of device from now on
0152         m_assistants << assistant;
0153 
0154         // start initial check for devices of this type
0155         checkDevicesFor( assistant );
0156     }
0157 
0158 }
0159 
0160 void
0161 MediaDeviceMonitor::deviceAdded( const QString &udi )
0162 {
0163     DEBUG_BLOCK
0164 
0165     // check if device is a known device
0166     checkDevice( udi );
0167 }
0168 
0169 void
0170 MediaDeviceMonitor::slotDeviceRemoved( const QString &udi )
0171 {
0172     DEBUG_BLOCK
0173 
0174     if ( m_udiAssistants.contains( udi ) )
0175     {
0176 
0177         m_udiAssistants.value( udi )->tellDisconnected( udi );
0178 
0179         m_udiAssistants.remove( udi );
0180     }
0181 
0182 
0183 //    Q_EMIT deviceRemoved( udi );
0184 }
0185 
0186 void
0187 MediaDeviceMonitor::slotAccessibilityChanged( bool accessible, const QString & udi)
0188 {
0189     // TODO: build a hack to force a device to become accessible or not
0190     // This means auto-mounting of Ipod, and ejecting of it too
0191 
0192     DEBUG_BLOCK
0193             debug() << "Accessibility changed to: " << ( accessible ? "true":"false" );
0194     if ( !accessible )
0195         deviceRemoved( udi );
0196     else
0197         deviceAdded( udi );
0198 }
0199 
0200 void
0201 MediaDeviceMonitor::slotDequeueWaitingAssistant()
0202 {
0203     checkDevicesFor( m_waitingassistants.at( m_nextassistant++ ) );
0204 }