You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
8.6 KiB
374 lines
8.6 KiB
/*
|
|
*
|
|
* $Id: sourceheader 380067 2005-01-19 13:03:46Z trueg $
|
|
* Copyright (C) 2005 Sebastian Trueg <trueg@k3b.org>
|
|
*
|
|
* This file is part of the K3b project.
|
|
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
* See the file "COPYING" for the exact licensing terms.
|
|
*/
|
|
|
|
#include "k3bmediacache.h"
|
|
#include "k3bmedium.h"
|
|
|
|
#include <k3bdevicemanager.h>
|
|
#include <k3bdeviceglobals.h>
|
|
#include <k3bscsicommand.h>
|
|
#include <k3bcore.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <tdeapplication.h>
|
|
#include <tdelocale.h>
|
|
|
|
#include <tqthread.h>
|
|
#include <tqmutex.h>
|
|
#include <tqevent.h>
|
|
|
|
|
|
// ////////////////////////////////////////////////////////////////////////////////
|
|
// MEDIA CACHE SUPPORT CLASSES
|
|
// ////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class K3bMediaCache::MediaChangeEvent : public TQCustomEvent
|
|
{
|
|
public:
|
|
static const int EventCode;
|
|
|
|
MediaChangeEvent( K3bDevice::Device* dev )
|
|
: TQCustomEvent( EventCode ),
|
|
m_device( dev ) {}
|
|
|
|
K3bDevice::Device* device() const { return m_device; }
|
|
|
|
private:
|
|
K3bDevice::Device* m_device;
|
|
};
|
|
|
|
const int K3bMediaCache::MediaChangeEvent::EventCode = TQEvent::User + 22;
|
|
|
|
|
|
class K3bMediaCache::DeviceEntry
|
|
{
|
|
public:
|
|
DeviceEntry( K3bMediaCache* cache, K3bDevice::Device* dev );
|
|
~DeviceEntry();
|
|
|
|
K3bMedium medium;
|
|
|
|
int blockedId;
|
|
|
|
TQMutex mutex;
|
|
|
|
K3bMediaCache::PollThread* thread;
|
|
|
|
K3bMediaCache* cache;
|
|
|
|
void clear() {
|
|
medium.reset();
|
|
}
|
|
};
|
|
|
|
|
|
class K3bMediaCache::PollThread : public TQThread
|
|
{
|
|
public:
|
|
PollThread( K3bMediaCache::DeviceEntry* de )
|
|
: m_deviceEntry( de ) {}
|
|
|
|
protected:
|
|
void run();
|
|
|
|
private:
|
|
K3bMediaCache::DeviceEntry* m_deviceEntry;
|
|
};
|
|
|
|
|
|
|
|
|
|
// ////////////////////////////////////////////////////////////////////////////////
|
|
// MEDIA CACHE SUPPORT CLASSES IMPL
|
|
// ////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
K3bMediaCache::DeviceEntry::DeviceEntry( K3bMediaCache* c, K3bDevice::Device* dev )
|
|
: medium(dev),
|
|
blockedId(0),
|
|
cache(c)
|
|
{
|
|
thread = new K3bMediaCache::PollThread( this );
|
|
}
|
|
|
|
|
|
K3bMediaCache::DeviceEntry::~DeviceEntry()
|
|
{
|
|
delete thread;
|
|
}
|
|
|
|
|
|
void K3bMediaCache::PollThread::run()
|
|
{
|
|
while( m_deviceEntry->blockedId == 0 ) {
|
|
bool unitReady = m_deviceEntry->medium.device()->testUnitReady();
|
|
bool mediumCached = ( m_deviceEntry->medium.diskInfo().diskState() != K3bDevice::STATE_NO_MEDIA );
|
|
|
|
//
|
|
// we only get the other information in case the disk state changed or if we have
|
|
// no info at all (FIXME: there are drives around that are not able to provide a proper
|
|
// disk state)
|
|
//
|
|
if( m_deviceEntry->medium.diskInfo().diskState() == K3bDevice::STATE_UNKNOWN ||
|
|
unitReady != mediumCached ) {
|
|
|
|
//
|
|
// The medium has changed. We need to update the information.
|
|
//
|
|
K3bMedium m( m_deviceEntry->medium.device() );
|
|
m.update();
|
|
|
|
// block the info since it is not valid anymore
|
|
m_deviceEntry->mutex.lock();
|
|
|
|
// m_deviceEntry->medium.update();
|
|
m_deviceEntry->medium = m;
|
|
|
|
//
|
|
// inform the media cache about the media change
|
|
//
|
|
if( m_deviceEntry->blockedId == 0 )
|
|
TQApplication::postEvent( m_deviceEntry->cache,
|
|
new K3bMediaCache::MediaChangeEvent( m_deviceEntry->medium.device() ) );
|
|
|
|
// the information is valid. let the info go.
|
|
m_deviceEntry->mutex.unlock();
|
|
}
|
|
|
|
if( m_deviceEntry->blockedId == 0 )
|
|
TQThread::sleep( 2 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ////////////////////////////////////////////////////////////////////////////////
|
|
// MEDIA CACHE IMPL
|
|
// ////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
K3bMediaCache::K3bMediaCache( TQObject* parent )
|
|
: TQObject( parent )
|
|
{
|
|
}
|
|
|
|
|
|
K3bMediaCache::~K3bMediaCache()
|
|
{
|
|
clearDeviceList();
|
|
}
|
|
|
|
|
|
int K3bMediaCache::blockDevice( K3bDevice::Device* dev )
|
|
{
|
|
DeviceEntry* e = findDeviceEntry( dev );
|
|
if( e ) {
|
|
if( e->blockedId )
|
|
return -1;
|
|
else {
|
|
// block the information
|
|
e->mutex.lock();
|
|
|
|
// create (hopefully) unique id
|
|
e->blockedId = TDEApplication::random();
|
|
|
|
// let the info go
|
|
e->mutex.unlock();
|
|
|
|
// wait for the thread to stop
|
|
e->thread->wait();
|
|
|
|
return e->blockedId;
|
|
}
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
bool K3bMediaCache::unblockDevice( K3bDevice::Device* dev, int id )
|
|
{
|
|
DeviceEntry* e = findDeviceEntry( dev );
|
|
if( e && e->blockedId && e->blockedId == id ) {
|
|
e->blockedId = 0;
|
|
|
|
// for security reasons we emit no medium signal at this point
|
|
// otherwise a job might resuse the old medium information
|
|
e->medium = K3bMedium( dev );
|
|
emit mediumChanged( dev );
|
|
|
|
// restart the poll thread
|
|
e->thread->start();
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
bool K3bMediaCache::isBlocked( K3bDevice::Device* dev )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( dev ) )
|
|
return ( e->blockedId != 0 );
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
K3bMedium K3bMediaCache::medium( K3bDevice::Device* dev )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( dev ) ) {
|
|
e->mutex.lock();
|
|
K3bMedium m = e->medium;
|
|
e->mutex.unlock();
|
|
return m;
|
|
}
|
|
else
|
|
return K3bMedium();
|
|
}
|
|
|
|
|
|
K3bDevice::DiskInfo K3bMediaCache::diskInfo( K3bDevice::Device* dev )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( dev ) ) {
|
|
e->mutex.lock();
|
|
K3bDevice::DiskInfo di = e->medium.diskInfo();
|
|
e->mutex.unlock();
|
|
return di;
|
|
}
|
|
else
|
|
return K3bDevice::DiskInfo();
|
|
}
|
|
|
|
|
|
K3bDevice::Toc K3bMediaCache::toc( K3bDevice::Device* dev )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( dev ) ) {
|
|
e->mutex.lock();
|
|
K3bDevice::Toc toc = e->medium.toc();
|
|
e->mutex.unlock();
|
|
return toc;
|
|
}
|
|
else
|
|
return K3bDevice::Toc();
|
|
}
|
|
|
|
|
|
K3bDevice::CdText K3bMediaCache::cdText( K3bDevice::Device* dev )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( dev ) ) {
|
|
e->mutex.lock();
|
|
K3bDevice::CdText cdt = e->medium.cdText();
|
|
e->mutex.unlock();
|
|
return cdt;
|
|
}
|
|
else
|
|
return K3bDevice::CdText();
|
|
}
|
|
|
|
|
|
TQValueList<int> K3bMediaCache::writingSpeeds( K3bDevice::Device* dev )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( dev ) ) {
|
|
e->mutex.lock();
|
|
TQValueList<int> ws = e->medium.writingSpeeds();
|
|
e->mutex.unlock();
|
|
return ws;
|
|
}
|
|
else
|
|
return TQValueList<int>();
|
|
}
|
|
|
|
|
|
TQString K3bMediaCache::mediumString( K3bDevice::Device* device, bool useContent )
|
|
{
|
|
if( DeviceEntry* e = findDeviceEntry( device ) ) {
|
|
return e->medium.shortString( useContent );
|
|
}
|
|
else
|
|
return TQString();
|
|
}
|
|
|
|
|
|
void K3bMediaCache::clearDeviceList()
|
|
{
|
|
kdDebug() << k_funcinfo << endl;
|
|
|
|
// make all the threads stop
|
|
for( TQMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
|
|
it != m_deviceMap.end(); ++it ) {
|
|
it.data()->blockedId = 1;
|
|
}
|
|
|
|
// and remove them
|
|
for( TQMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
|
|
it != m_deviceMap.end(); ++it ) {
|
|
kdDebug() << k_funcinfo << " waiting for info thread " << it.key()->blockDeviceName() << " to finish" << endl;
|
|
it.data()->thread->wait();
|
|
delete it.data();
|
|
}
|
|
|
|
m_deviceMap.clear();
|
|
}
|
|
|
|
|
|
void K3bMediaCache::buildDeviceList( K3bDevice::DeviceManager* dm )
|
|
{
|
|
// remember blocked ids
|
|
TQMap<K3bDevice::Device*, int> blockedIds;
|
|
for( TQMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
|
|
it != m_deviceMap.end(); ++it )
|
|
blockedIds.insert( it.key(), it.data()->blockedId );
|
|
|
|
clearDeviceList();
|
|
|
|
const TQPtrList<K3bDevice::Device>& devices = dm->allDevices();
|
|
for( TQPtrListIterator<K3bDevice::Device> it( devices ); *it; ++it ) {
|
|
m_deviceMap.insert( *it, new DeviceEntry( this, *it ) );
|
|
TQMap<K3bDevice::Device*, int>::const_iterator bi_it = blockedIds.find( *it );
|
|
if( bi_it != blockedIds.end() )
|
|
m_deviceMap[*it]->blockedId = bi_it.data();
|
|
}
|
|
|
|
// start all the polling threads
|
|
for( TQMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.begin();
|
|
it != m_deviceMap.end(); ++it ) {
|
|
if( !it.data()->blockedId )
|
|
it.data()->thread->start();
|
|
}
|
|
}
|
|
|
|
|
|
K3bMediaCache::DeviceEntry* K3bMediaCache::findDeviceEntry( K3bDevice::Device* dev )
|
|
{
|
|
TQMap<K3bDevice::Device*, DeviceEntry*>::iterator it = m_deviceMap.find( dev );
|
|
if( it != m_deviceMap.end() )
|
|
return it.data();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
void K3bMediaCache::customEvent( TQCustomEvent* e )
|
|
{
|
|
if( e->type() == MediaChangeEvent::EventCode )
|
|
emit mediumChanged( static_cast<MediaChangeEvent*>( e )->device() );
|
|
}
|
|
|
|
#include "k3bmediacache.moc"
|