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.
k3b/libk3b/projects/audiocd/k3baudiocdtracksource.cpp

263 lines
6.8 KiB

/*
*
* $Id: k3baudiocdtracksource.cpp 676194 2007-06-16 08:59:19Z 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 "k3baudiocdtracksource.h"
#include "k3baudiotrack.h"
#include "k3baudiodoc.h"
#include <k3bthreadwidget.h>
#include <k3btoc.h>
#include <k3bdevice.h>
#include <k3bdevicemanager.h>
#include <k3bcdparanoialib.h>
#include <k3bdeviceselectiondialog.h>
#include <k3bcore.h>
#include <klocale.h>
#include <kdebug.h>
K3bAudioCdTrackSource::K3bAudioCdTrackSource( const K3bDevice::Toc& toc, int cdTrackNumber,
const K3bCddbResultEntry& cddb, K3bDevice::Device* dev )
: K3bAudioDataSource(),
m_discId( toc.discId() ),
m_length( toc[cdTrackNumber-1].length() ),
m_toc( toc ),
m_cdTrackNumber( cdTrackNumber ),
m_cddbEntry( cddb ),
m_lastUsedDevice( dev ),
m_cdParanoiaLib( 0 ),
m_initialized( false )
{
}
K3bAudioCdTrackSource::K3bAudioCdTrackSource( unsigned int discid, const K3b::Msf& length, int cdTrackNumber,
const TQString& artist, const TQString& title,
const TQString& cdArtist, const TQString& cdTitle )
: K3bAudioDataSource(),
m_discId( discid ),
m_length( length ),
m_cdTrackNumber( cdTrackNumber ),
m_lastUsedDevice( 0 ),
m_cdParanoiaLib( 0 ),
m_initialized( false )
{
for( int i = 1; i < cdTrackNumber; ++i ) {
m_cddbEntry.titles.append( TQString() );
m_cddbEntry.artists.append( TQString() );
}
m_cddbEntry.titles.append( title );
m_cddbEntry.artists.append( artist );
m_cddbEntry.cdTitle = cdTitle;
m_cddbEntry.cdArtist = cdArtist;
}
K3bAudioCdTrackSource::K3bAudioCdTrackSource( const K3bAudioCdTrackSource& source )
: K3bAudioDataSource( source ),
m_discId( source.m_discId ),
m_toc( source.m_toc ),
m_cdTrackNumber( source.m_cdTrackNumber ),
m_cddbEntry( source.m_cddbEntry ),
m_lastUsedDevice( source.m_lastUsedDevice ),
m_cdParanoiaLib( 0 ),
m_initialized( false )
{
}
K3bAudioCdTrackSource::~K3bAudioCdTrackSource()
{
closeParanoia();
delete m_cdParanoiaLib;
}
bool K3bAudioCdTrackSource::initParanoia()
{
if( !m_initialized ) {
if( !m_cdParanoiaLib )
m_cdParanoiaLib = K3bCdparanoiaLib::create();
if( m_cdParanoiaLib ) {
m_lastUsedDevice = searchForAudioCD();
// ask here for the cd since searchForAudioCD() may also be called from outside
if( !m_lastUsedDevice ) {
// could not find the CD, so ask for it
TQString s = i18n("Please insert Audio CD %1%2")
.tqarg(m_discId, 0, 16)
.tqarg(m_cddbEntry.cdTitle.isEmpty() || m_cddbEntry.cdArtist.isEmpty()
? TQString()
: " (" + m_cddbEntry.cdArtist + " - " + m_cddbEntry.cdTitle + ")");
while( K3bDevice::Device* dev = K3bThreadWidget::selectDevice( track()->doc()->view(), s ) ) {
if( searchForAudioCD( dev ) ) {
m_lastUsedDevice = dev;
break;
}
}
}
// user canceled
if( !m_lastUsedDevice )
return false;
k3bcore->blockDevice( m_lastUsedDevice );
if( m_toc.isEmpty() )
m_toc = m_lastUsedDevice->readToc();
if( !m_cdParanoiaLib->initParanoia( m_lastUsedDevice, m_toc ) ) {
k3bcore->unblockDevice( m_lastUsedDevice );
return false;
}
if( doc() ) {
m_cdParanoiaLib->setParanoiaMode( doc()->audioRippingParanoiaMode() );
m_cdParanoiaLib->setNeverSkip( !doc()->audioRippingIgnoreReadErrors() );
m_cdParanoiaLib->setMaxRetries( doc()->audioRippingRetries() );
}
m_cdParanoiaLib->initReading( m_toc[m_cdTrackNumber-1].firstSector().lba() + startOffset().lba() + m_position.lba(),
m_toc[m_cdTrackNumber-1].firstSector().lba() + lastSector().lba() );
// we only block during the initialization because we cannot determine the end of the reading process :(
k3bcore->unblockDevice( m_lastUsedDevice );
m_initialized = true;
kdDebug() << "(K3bAudioCdTrackSource) initialized." << endl;
}
}
return m_initialized;
}
void K3bAudioCdTrackSource::closeParanoia()
{
if( m_cdParanoiaLib && m_initialized ) {
m_cdParanoiaLib->close();
}
m_initialized = false;
}
K3bDevice::Device* K3bAudioCdTrackSource::searchForAudioCD() const
{
kdDebug() << "(K3bAudioCdTrackSource::searchForAudioCD()" << endl;
// first try the saved device
if( m_lastUsedDevice && searchForAudioCD( m_lastUsedDevice ) )
return m_lastUsedDevice;
const TQPtrList<K3bDevice::Device>& devices = k3bcore->deviceManager()->readingDevices();
for( TQPtrListIterator<K3bDevice::Device> it(devices); *it; ++it ) {
if( searchForAudioCD( *it ) ) {
return *it;
}
}
kdDebug() << "(K3bAudioCdTrackSource::searchForAudioCD) failed." << endl;
return 0;
}
bool K3bAudioCdTrackSource::searchForAudioCD( K3bDevice::Device* dev ) const
{
kdDebug() << "(K3bAudioCdTrackSource::searchForAudioCD(" << dev->description() << ")" << endl;
K3bDevice::Toc toc = dev->readToc();
return ( toc.discId() == m_discId );
}
void K3bAudioCdTrackSource::setDevice( K3bDevice::Device* dev )
{
if( dev && dev != m_lastUsedDevice ) {
m_lastUsedDevice = dev;
if( m_initialized ) {
}
}
}
K3b::Msf K3bAudioCdTrackSource::originalLength() const
{
return m_length;
}
bool K3bAudioCdTrackSource::seek( const K3b::Msf& msf )
{
// HACK: to reinitialize every time we restart the decoding
if( msf == 0 && m_cdParanoiaLib )
closeParanoia();
m_position = msf;
if( m_cdParanoiaLib )
m_cdParanoiaLib->initReading( m_toc[m_cdTrackNumber-1].firstSector().lba() + startOffset().lba() + m_position.lba(),
m_toc[m_cdTrackNumber-1].firstSector().lba() + lastSector().lba() );
return true;
}
int K3bAudioCdTrackSource::read( char* data, unsigned int )
{
if( initParanoia() ) {
int status = 0;
char* buf = m_cdParanoiaLib->read( &status, 0, false /* big endian */ );
if( status == K3bCdparanoiaLib::S_OK ) {
if( buf == 0 ) {
// done
closeParanoia();
return 0;
}
else {
++m_position;
::memcpy( data, buf, CD_FRAMESIZE_RAW );
return CD_FRAMESIZE_RAW;
}
}
else {
// in case the reading fails we go back to "not initialized"
closeParanoia();
return -1;
}
}
else
return -1;
}
TQString K3bAudioCdTrackSource::type() const
{
return i18n("CD Track");
}
TQString K3bAudioCdTrackSource::sourceComment() const
{
return i18n("Track %1 from Audio CD %2").tqarg(m_cdTrackNumber).tqarg(m_discId,0,16);
}
K3bAudioDataSource* K3bAudioCdTrackSource::copy() const
{
return new K3bAudioCdTrackSource( *this );
}