|
|
|
/*
|
|
|
|
*
|
|
|
|
* $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 <tdelocale.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")
|
|
|
|
.arg(m_discId, 0, 16)
|
|
|
|
.arg(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").arg(m_cdTrackNumber).arg(m_discId,0,16);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
K3bAudioDataSource* K3bAudioCdTrackSource::copy() const
|
|
|
|
{
|
|
|
|
return new K3bAudioCdTrackSource( *this );
|
|
|
|
}
|