File indexing completed on 2025-02-09 05:40:26
0001 /* 0002 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 #include <config-k3b.h> 0006 0007 #include "k3bcore.h" 0008 #include "k3bjob.h" 0009 #include "k3bmediacache.h" 0010 0011 #include "k3bdevicemanager.h" 0012 #include "k3bexternalbinmanager.h" 0013 #include "k3bdefaultexternalprograms.h" 0014 #include "k3bglobals.h" 0015 #include "k3bversion.h" 0016 #include "k3bthreadwidget.h" 0017 #include "k3bglobalsettings.h" 0018 #include "k3bpluginmanager.h" 0019 #include "k3b_i18n.h" 0020 0021 #include <KConfig> 0022 #include <KConfigGroup> 0023 #ifdef WITH_NEW_SOLID_JOB 0024 #include <Solid/Power> 0025 #endif 0026 0027 #include <QCoreApplication> 0028 #include <QEvent> 0029 #include <QMutex> 0030 #include <QMutexLocker> 0031 #include <QThread> 0032 0033 0034 static QThread* s_guiThreadHandle = 0; 0035 0036 // We cannot use QWaitCondition here since the event might be handled faster 0037 // than the thread starts the waiting 0038 class DeviceBlockingEventDoneCondition { 0039 public: 0040 DeviceBlockingEventDoneCondition() 0041 : m_done(false) { 0042 } 0043 0044 void done() { 0045 QMutexLocker locker( &m_doneMutex ); 0046 m_done = true; 0047 } 0048 0049 void wait() { 0050 while( true ) { 0051 QMutexLocker locker( &m_doneMutex ); 0052 bool done = m_done; 0053 if( done ) 0054 return; 0055 } 0056 } 0057 0058 private: 0059 QMutex m_doneMutex; 0060 bool m_done; 0061 }; 0062 0063 0064 class DeviceBlockingEvent : public QEvent 0065 { 0066 public: 0067 DeviceBlockingEvent( bool block_, K3b::Device::Device* dev, DeviceBlockingEventDoneCondition* cond_, bool* success_ ) 0068 : QEvent( QEvent::User ), 0069 block(block_), 0070 device(dev), 0071 cond(cond_), 0072 success(success_) { 0073 } 0074 0075 bool block; 0076 K3b::Device::Device* device; 0077 DeviceBlockingEventDoneCondition* cond; 0078 bool* success; 0079 }; 0080 0081 0082 class K3b::Core::Private { 0083 public: 0084 Private() 0085 : version( LIBK3B_VERSION ), 0086 mediaCache(0), 0087 deviceManager(0), 0088 externalBinManager(0), 0089 pluginManager(0), 0090 globalSettings(0) { 0091 } 0092 0093 K3b::Version version; 0094 K3b::MediaCache* mediaCache; 0095 K3b::Device::DeviceManager* deviceManager; 0096 K3b::ExternalBinManager* externalBinManager; 0097 K3b::PluginManager* pluginManager; 0098 K3b::GlobalSettings* globalSettings; 0099 0100 QList<K3b::Job*> runningJobs; 0101 QList<K3b::Device::Device*> blockedDevices; 0102 0103 #ifdef WITH_NEW_SOLID_JOB 0104 Solid::InhibitionJob *inhibitSleepJob = nullptr; 0105 Solid::InhibitionJob *inhibitNoneJob = nullptr; 0106 #endif 0107 }; 0108 0109 0110 0111 K3b::Core* K3b::Core::s_k3bCore = 0; 0112 0113 0114 0115 K3b::Core::Core( QObject* parent ) 0116 : QObject( parent ) 0117 { 0118 d = new Private(); 0119 0120 if( s_k3bCore ) 0121 qFatal("ONLY ONE INSTANCE OF K3BCORE ALLOWED!"); 0122 s_k3bCore = this; 0123 0124 // ew are probably constructed in the GUi thread :( 0125 s_guiThreadHandle = QThread::currentThread(); 0126 0127 // create the thread widget instance in the GUI thread 0128 K3b::ThreadWidget::instance(); 0129 } 0130 0131 0132 K3b::Core::~Core() 0133 { 0134 s_k3bCore = 0; 0135 0136 delete d->globalSettings; 0137 delete d; 0138 } 0139 0140 0141 K3b::MediaCache* K3b::Core::mediaCache() const 0142 { 0143 if ( !d->mediaCache ) { 0144 // create the media cache but do not connect it to the device manager 0145 // yet to speed up application start. We connect it in init() 0146 // once the devicemanager has scanned for devices. 0147 d->mediaCache = new K3b::MediaCache( const_cast<Core*>( this ) ); 0148 } 0149 return d->mediaCache; 0150 } 0151 0152 0153 K3b::Device::DeviceManager* K3b::Core::deviceManager() const 0154 { 0155 if( !d->deviceManager ) { 0156 d->deviceManager = createDeviceManager(); 0157 } 0158 return d->deviceManager; 0159 } 0160 0161 0162 K3b::ExternalBinManager* K3b::Core::externalBinManager() const 0163 { 0164 if( !d->externalBinManager ) { 0165 d->externalBinManager = new ExternalBinManager( const_cast<Core*>( this ) ); 0166 addDefaultPrograms( d->externalBinManager ); 0167 } 0168 return d->externalBinManager; 0169 } 0170 0171 0172 K3b::PluginManager* K3b::Core::pluginManager() const 0173 { 0174 if( !d->pluginManager ) 0175 d->pluginManager = new K3b::PluginManager( const_cast<Core*>( this ) ); 0176 return d->pluginManager; 0177 } 0178 0179 0180 K3b::GlobalSettings* K3b::Core::globalSettings() const 0181 { 0182 if( !d->globalSettings ) { 0183 d->globalSettings = new GlobalSettings(); 0184 } 0185 return d->globalSettings; 0186 } 0187 0188 0189 K3b::Version K3b::Core::version() const 0190 { 0191 return d->version; 0192 } 0193 0194 0195 void K3b::Core::init() 0196 { 0197 // load the plugins before doing anything else 0198 // they might add external bins 0199 pluginManager()->loadAll(); 0200 0201 externalBinManager()->search(); 0202 0203 deviceManager()->scanBus(); 0204 0205 mediaCache()->buildDeviceList( deviceManager() ); 0206 } 0207 0208 0209 K3b::Device::DeviceManager* K3b::Core::createDeviceManager() const 0210 { 0211 return new K3b::Device::DeviceManager( const_cast<Core*>( this ) ); 0212 } 0213 0214 0215 void K3b::Core::readSettings( KSharedConfig::Ptr c ) 0216 { 0217 globalSettings()->readSettings( c->group( QStringLiteral("General Options") ) ); 0218 deviceManager()->readConfig( c->group( QStringLiteral("Devices") ) ); 0219 externalBinManager()->readConfig( c->group( QStringLiteral("External Programs") ) ); 0220 } 0221 0222 0223 void K3b::Core::saveSettings( KSharedConfig::Ptr c ) 0224 { 0225 KConfigGroup grp( c, QStringLiteral("General Options") ); 0226 grp.writeEntry( "config version", version().toString() ); 0227 0228 deviceManager()->saveConfig( c->group( QStringLiteral("Devices") ) ); 0229 externalBinManager()->saveConfig( c->group( QStringLiteral("External Programs") ) ); 0230 d->globalSettings->saveSettings( c->group( QStringLiteral("General Options") ) ); 0231 } 0232 0233 0234 void K3b::Core::registerJob(K3b::Job* job) 0235 { 0236 d->runningJobs.append(job); 0237 emit jobStarted(job); 0238 if (K3b::BurnJob* bj = dynamic_cast<K3b::BurnJob*>(job)) { 0239 #ifdef WITH_NEW_SOLID_JOB 0240 d->inhibitSleepJob = Solid::Power::inhibit(Solid::Power::Sleep, 0241 i18n("Inhibiting sleep for disc writing")); 0242 if (d->inhibitSleepJob) 0243 d->inhibitSleepJob->start(); 0244 #endif 0245 emit burnJobStarted(bj); 0246 } 0247 } 0248 0249 0250 void K3b::Core::unregisterJob(K3b::Job* job) 0251 { 0252 d->runningJobs.removeAll(job); 0253 emit jobFinished(job); 0254 if (K3b::BurnJob* bj = dynamic_cast<K3b::BurnJob*>(job)) { 0255 #ifdef WITH_NEW_SOLID_JOB 0256 d->inhibitNoneJob = Solid::Power::inhibit(Solid::None, 0257 i18n("Disable inhibition for disc writing")); 0258 if (d->inhibitNoneJob) 0259 d->inhibitNoneJob->start(); 0260 #endif 0261 emit burnJobFinished(bj); 0262 } 0263 } 0264 0265 0266 bool K3b::Core::jobsRunning() const 0267 { 0268 return !d->runningJobs.isEmpty(); 0269 } 0270 0271 0272 QList<K3b::Job*> K3b::Core::runningJobs() const 0273 { 0274 return d->runningJobs; 0275 } 0276 0277 0278 bool K3b::Core::blockDevice( K3b::Device::Device* dev ) 0279 { 0280 if( QThread::currentThread() == s_guiThreadHandle ) { 0281 return internalBlockDevice( dev ); 0282 } 0283 else { 0284 bool success = false; 0285 DeviceBlockingEventDoneCondition w; 0286 QCoreApplication::postEvent( this, new DeviceBlockingEvent( true, dev, &w, &success ) ); 0287 w.wait(); 0288 return success; 0289 } 0290 } 0291 0292 0293 void K3b::Core::unblockDevice( K3b::Device::Device* dev ) 0294 { 0295 if( QThread::currentThread() == s_guiThreadHandle ) { 0296 internalUnblockDevice( dev ); 0297 } 0298 else { 0299 DeviceBlockingEventDoneCondition w; 0300 QCoreApplication::postEvent( this, new DeviceBlockingEvent( false, dev, &w, 0 ) ); 0301 w.wait(); 0302 } 0303 } 0304 0305 0306 bool K3b::Core::internalBlockDevice( K3b::Device::Device* dev ) 0307 { 0308 if( !d->blockedDevices.contains( dev ) ) { 0309 d->blockedDevices.append( dev ); 0310 return true; 0311 } 0312 else 0313 return false; 0314 } 0315 0316 0317 void K3b::Core::internalUnblockDevice( K3b::Device::Device* dev ) 0318 { 0319 d->blockedDevices.removeAll( dev ); 0320 } 0321 0322 0323 bool K3b::Core::deviceBlocked( Device::Device* dev ) const 0324 { 0325 return d->blockedDevices.contains( dev ); 0326 } 0327 0328 0329 void K3b::Core::customEvent( QEvent* e ) 0330 { 0331 if( DeviceBlockingEvent* de = dynamic_cast<DeviceBlockingEvent*>(e) ) { 0332 if( de->block ) 0333 *de->success = internalBlockDevice( de->device ); 0334 else 0335 internalUnblockDevice( de->device ); 0336 de->cond->done(); 0337 } 0338 } 0339 0340 #include "moc_k3bcore.cpp"