File indexing completed on 2024-06-16 04:33:37

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"