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.
tdemultimedia/krec/krecfile.cpp

458 lines
14 KiB

/***************************************************************************
copyright : (C) 2003 by Arnold Krille
email : arnold@arnoldarts.de
***************************************************************************/
/***************************************************************************
* *
* 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; version 2 of the License. *
* *
***************************************************************************/
#include "krecfile.h"
#include "krecfile.moc"
#include "krecglobal.h"
#include "krecnewproperties.h"
#include <kdebug.h>
#include <tdeapplication.h>
#include <ktempdir.h>
#include <ktempfile.h>
#include <ktar.h>
#include <tdeio/job.h>
#include <klocale.h>
#include <ksimpleconfig.h>
#include <tqdir.h>
#include <tqfileinfo.h>
#include <kmessagebox.h>
#include <tqtimer.h>
#include <tqdatastream.h>
#include <math.h>
void KRecFile::init() {
_pos = 0;
_size = 0;
_filename = TQString();
_currentBuffer = 0;
_dir = new KTempDir();
_config = new KSimpleConfig( _dir->name()+"project.rc", false );
}
KRecFile::KRecFile( TQObject* p, const char* n )
: TQObject( p,n )
, _saved( false )
{
init();
kdDebug( 60005 ) << k_funcinfo << "_dir->name(): " << _dir->name() << endl;
_dir->setAutoDelete( true );
KRecNewProperties* dialog = new KRecNewProperties( KRecGlobal::the()->mainWidget() );
if ( dialog->usedefaults() )
KRecGlobal::the()->message( i18n( "Using default properties for the new file" ) );
else
dialog->exec();
_samplerate = dialog->samplerate();
_channels = dialog->channels();
_bits = dialog->bits();
saveProps();
delete dialog;
}
KRecFile::KRecFile( const TQString &filename, TQObject* p, const char* n )
: TQObject( p,n )
, _saved( true )
{
init();
_filename = filename;
kdDebug( 60005 ) << k_funcinfo << "_dir->name(): " << _dir->name() << endl;
_dir->setAutoDelete( true );
KTar *tar = new KTar( _filename, "application/x-gzip" );
tar->open( IO_ReadOnly );
int i=0; while ( _filename.find( '/', i ) != -1 ) i++; // Find last '/'
TQString basename = _filename.right( _filename.length()-i );
basename = basename.left( basename.length()-5 );
const KArchiveDirectory *dir = dynamic_cast<const KArchiveDirectory*>( tar->directory()->entry( basename ) );
dir->copyTo( _dir->name() );
delete _config;
_config = new KSimpleConfig( _dir->name()+"project.rc", false );
loadProps();
int c = _config->readNumEntry( "Files" );
//kdDebug( 60005 ) << c << " Files to load" << endl;
for ( int i=0; i<c; i++ ) {
//kdDebug( 60005 ) << "Loading file " << i << endl;
_config->setGroup( "File-" + TQString::number( i ) );
newBuffer( KRecBuffer::fromConfig( _config, _dir->qDir(), this ) );
}
KRecGlobal::the()->message( i18n( "\'%1\' loaded." ).arg( filename ) );
delete tar;
_saved = true;
//kdDebug( 60005 ) << "Buffers opened: " << _buffers.count() << endl;
}
KRecFile::~KRecFile() {
kdDebug( 60005 ) << k_funcinfo << endl;
TQValueList<KRecBuffer*>::iterator it;
for ( it = _buffers.begin(); it != _buffers.end(); ++it )
delete ( *it );
_buffers.clear();
delete _dir;
delete _config;
//kdDebug( 60005 ) << k_funcinfo << "done." << endl;
}
TQString KRecFile::filename() { return _filename; }
void KRecFile::filename( const TQString &n ) {
if ( _filename!=n ) {
_filename = n;
emit filenameChanged( _filename );
}
}
void KRecFile::writeData( Arts::mcopbyte* /*data*/, uint /*length*/ ) {
kdDebug( 60005 ) << k_funcinfo << endl;
}
void KRecFile::writeData( TQByteArray* data ) {
kdDebug( 60005 ) << k_funcinfo << endl;
if ( _currentBuffer!=-1 ) _buffers[ _currentBuffer ]->writeData( data );
_saved = false;
}
void KRecFile::writeData( TQByteArray& data ) {
if ( _currentBuffer!=-1 ) _buffers[ _currentBuffer ]->writeData( data );
_saved = false;
}
void KRecFile::save( const TQString &fname ) {
TQString filetosave = fname;
//kdDebug( 60005 ) << k_funcinfo << filename << endl;
if ( saved() ) {
KRecGlobal::the()->message( i18n( "No need to save." ) );
return;
}
KRecGlobal::the()->message( i18n( "Saving in progress..." ) );
filename( fname );
TQString tmpname;
{
KTempFile *tmp = new KTempFile();
tmp->setAutoDelete( true );
tmpname = tmp->name();
delete tmp;
}
saveProps();
KTar *tar = new KTar( tmpname, "application/x-gzip" );
tar->open( IO_WriteOnly );
int i=0; while ( fname.find( '/', i ) != -1 ) i++; // Find last '/'
TQString basename = fname.right( fname.length()-i );
if ( basename.endsWith( ".krec" ) )
basename = basename.left( basename.length()-5 );
else {
filetosave = fname + ".krec";
filename( filetosave );
}
tar->addLocalDirectory( _dir->name(), basename );
delete tar;
TDEIO::file_move( tmpname, filetosave, -1, true, false, true );
KRecGlobal::the()->message( i18n( "Saving \"%1\" was successful." ).arg( filename() ) );
_saved = true;
}
void KRecFile::exportwave( const TQString &filename ) {
kdDebug( 60005 ) << k_funcinfo << filename << endl;
}
TQByteArray* KRecFile::getData( int ) {
kdDebug( 60005 ) << k_funcinfo << endl;
return 0;
}
void KRecFile::getData( TQByteArray& data ) {
KRecBuffer* current = getTopBuffer_buffer( _pos );
if ( current ) {
//kdDebug( 60005 ) << "_pos=" << _pos << "(" << samplesToOffset( _pos ) << ") current->startpos()=" << current->startpos() << "(" << samplesToOffset( current->startpos() ) << ") that is " << samplesToOffset( _pos - current->startpos() ) << endl;
current->setPos( samplesToOffset( _pos - current->startpos() ) );
current->getData( data );
} else {
for ( uint i=0; i<data.size(); i++ )
data[ i ] = 0;
}
newPos( _pos + offsetToSamples( data.size() ) );
if ( position() >= size() ) emit endReached();
}
// * * * Position * * *
void KRecFile::newPos( int p ) {
if ( _pos != p ) {
_pos = p;
emit posChanged( _pos );
}
}
void KRecFile::newPos( KRecBuffer* buffer, TQIODevice::Offset p ) {
newPos( buffer->startpos() + offsetToSamples( p ) );
}
void KRecFile::newSize( KRecBuffer* buffer, TQIODevice::Offset p ) {
if ( buffer->startpos() + offsetToSamples( p ) > _size ) {
_size = buffer->startpos() + offsetToSamples( p );
}
emit sizeChanged( _size );
}
/// * * * Frames <-> Offset and more * * *
int KRecFile::offsetToSamples( TQIODevice::Offset n ) const {
int out = n / channels();
if ( bits() == 16 ) out /= 2;
return out;
}
TQIODevice::Offset KRecFile::samplesToOffset( int n ) const {
TQIODevice::Offset out = n * channels();
if ( bits() == 16 ) out *= 2;
return out;
}
/// * * * Properties <-> TDEConfig * * *
void KRecFile::saveProps() {
kdDebug( 60005 ) << k_funcinfo << endl;
_config->setGroup( "General" );
_config->writeEntry( "Samplerate", _samplerate );
_config->writeEntry( "Bits", _bits );
_config->writeEntry( "Channels", _channels );
_config->writeEntry( "Files", _buffers.count() );
for ( uint i=0; i<_buffers.count(); i++ ) {
//kdDebug( 60005 ) << "Writing config " << i << endl;
_config->setGroup( "File-" + TQString::number( i ) );
_buffers[ i ]->writeConfig( _config );
}
_config->sync();
}
void KRecFile::loadProps() {
kdDebug( 60005 ) << k_funcinfo << endl;
_config->setGroup( "General" );
_samplerate = _config->readNumEntry( "Samplerate", 44100 );
_bits = _config->readNumEntry( "Bits", 16 );
_channels = _config->readNumEntry( "Channels", 2 );
}
/// * * * NewBuffer * * *
void KRecFile::newBuffer( const TQString &filename ) {
kdDebug( 60005 ) << k_funcinfo << filename << endl;
newBuffer( new KRecBuffer( filename, _pos, true, this ) );
}
void KRecFile::newBuffer( KRecBuffer* buffer ) {
kdDebug( 60005 ) << k_funcinfo << endl;
connect( buffer, TQT_SIGNAL( posChanged( KRecBuffer*, TQIODevice::Offset ) ), this, TQT_SLOT( newPos( KRecBuffer*, TQIODevice::Offset ) ) );
connect( buffer, TQT_SIGNAL( sizeChanged( KRecBuffer*, TQIODevice::Offset ) ), this, TQT_SLOT( newSize( KRecBuffer*, TQIODevice::Offset ) ) );
connect( buffer, TQT_SIGNAL( deleteSelf( KRecBuffer* ) ), this, TQT_SLOT( deleteBuffer( KRecBuffer* ) ) );
_buffers.append( buffer );
newSize( buffer, buffer->size() );
_currentBuffer = _buffers.findIndex( buffer );
emit sNewBuffer( buffer );
_saved = false;
}
void KRecFile::newBuffer() {
kdDebug( 60005 ) << k_funcinfo << endl;
newBuffer( _dir->name() + "file" + TQString::number( _buffers.count() ) + ".raw" );
}
void KRecFile::deleteBuffer( KRecBuffer* b ) {
kdDebug( 60005 ) << k_funcinfo << b << endl;
emit sDeleteBuffer( b );
delete b;
if ( _buffers.remove( b ) )
_currentBuffer = -1;
KRecGlobal::the()->message( i18n( "Part deleted." ) );
_saved = false;
}
/// * * * helper * * *
KRecBuffer* KRecFile::getTopBuffer_buffer( int pos ) {
//kdDebug( 60005 ) << k_funcinfo << pos << endl;
TQValueList<KRecBuffer*>::iterator it = _buffers.begin();
KRecBuffer* out = 0;
while ( it != _buffers.end() ) {
if ( ( *it )->startpos() <= pos && offsetToSamples( ( *it )->size() ) + ( *it )->startpos() > pos && ( *it )->active() )
out = ( *it );
++it;
}
return out;
}
int KRecFile::getTopBuffer_int( int pos ) {
return _buffers.findIndex( getTopBuffer_buffer( pos ) );
}
/// * * * KRecBuffer * * *
KRecBuffer::KRecBuffer( const TQString &filename, int startpos, bool a, KRecFile* p, const char* n )
: TQObject( p,n )
, _krecfile( p )
, _file( new TQFile( filename ) )
, _stream( new TQDataStream( _file ) )
, _fileinfo( new TQFileInfo( filename ) )
, _active( a )
, _pos( 0 ), _start( startpos )
, _title( _fileinfo->fileName() )
, _comment( TQString() )
{
kdDebug( 60005 ) << k_funcinfo << filename << " " << startpos << endl;
_open = _file->open( IO_Raw | IO_ReadWrite );
setPos( _file->at() );
if ( _open ) kdDebug( 60005 ) << k_funcinfo << "Open successfull!" << endl;
else kdDebug( 60005 ) << endl << k_funcinfo << "Could not open file!" << endl << endl;
}
KRecBuffer::~KRecBuffer() {
kdDebug( 60005 ) << k_funcinfo << endl;
if ( _open ) {
_file->close();
_open = false;
_file->remove();
}
//kdDebug( 60005 ) << k_funcinfo << "done." << endl;
}
void KRecBuffer::writeConfig( TDEConfig* config ) {
//kdDebug( 60005 ) << k_funcinfo << config << endl;
config->writeEntry( "Filename", _fileinfo->fileName() );
config->writeEntry( "StartPos", _start );
config->writeEntry( "Activated", _active );
config->writeEntry( "Title", _title );
config->writeEntry( "Comment", _comment );
}
KRecBuffer* KRecBuffer::fromConfig( TDEConfig* config, TQDir* dir, KRecFile* p, const char* n ) {
kdDebug( 60005 ) << k_funcinfo << config << endl;
KRecBuffer* tmp = new KRecBuffer( dir->path() + "/" + config->readEntry( "Filename" ),
config->readNumEntry( "StartPos" ),
config->readBoolEntry( "Activated", true ),
p, n );
tmp->setTitle( config->readEntry( "Title", tmp->filename() ) );
tmp->setComment( config->readEntry( "Comment", TQString() ) );
return tmp;
}
void KRecBuffer::writeData( Arts::mcopbyte* /*data*/, uint /*length*/ ) {
kdDebug( 60005 ) << k_funcinfo << endl;
}
void KRecBuffer::writeData( TQByteArray* data ) {
kdDebug( 60005 ) << k_funcinfo << endl;
writeData( *data );
/* if ( _open ) {
_file->at( _pos );
_file->writeBlock( *data );
setPos( _file->at() );
emit sizeChanged( this, size() );
}*/
}
void KRecBuffer::writeData( TQByteArray& data ) {
//kdDebug( 60005 ) << k_funcinfo << endl;
if ( _open ) {
_file->at( _pos );
_file->writeBlock( data );
setPos( _file->at() );
emit sizeChanged( this, size() );
}
}
void KRecBuffer::getData( TQByteArray& data ) {
//kdDebug( 60005 ) << k_funcinfo << "data.size()" << data.size() << " _pos" << _pos << endl;
if ( _pos > _file->size() )
kdWarning() << "Trying to access behind file!" << endl;
else {
if ( _open ) {
_file->at( _pos );
//kdDebug( 60005 ) << "Reading " << _file->readBlock( ( char* )data.data(), data.size() ) << "bytes into data." << endl;
//kdDebug( 60005 ) << "data.size()" << data.size() << endl;
for ( uint i=0; i<data.size(); i++ ) {
if ( !_file->atEnd() )
data.data()[ i ] = _file->getch();
else
data.data()[ i ] = 0;
}
//setPos( _file->at() );
}
}
}
void KRecBuffer::setPos( TQIODevice::Offset p ) {
if ( p!=_pos ) {
_pos = p;
emit posChanged( this, _pos );
//kdDebug( 60005 ) << k_funcinfo << _pos << endl;
}
}
int KRecBuffer::startpos() const { return _start; }
TQIODevice::Offset KRecBuffer::size() const { return _file->size(); }
TQString KRecBuffer::filename() const { return _fileinfo->fileName(); }
TQString KRecBuffer::title() const { return _title; }
TQString KRecBuffer::comment() const { return _comment; }
void KRecBuffer::setTitle( const TQString &n ) {
if ( _title != n ) {
_title = n;
emit somethingChanged();
}
}
void KRecBuffer::setComment( const TQString &n ) {
if ( _comment != n ) {
_comment = n;
emit somethingChanged();
}
}
bool KRecBuffer::active() const { return _active; }
void KRecBuffer::setActive( bool n ) {
if ( _active != n ) {
_active = n;
emit activeChanged( _active );
emit somethingChanged();
}
}
void KRecBuffer::deleteBuffer() {
if ( KMessageBox::warningContinueCancel( KRecGlobal::the()->mainWidget(), i18n( "Do you really want to delete the selected part '%1'?" ).arg( filename() ), i18n("Delete Part?"), KStdGuiItem::del() ) == KMessageBox::Continue )
_krecfile->deleteBuffer( this );
}
float KRecBuffer::getSample( int pos, int /*channel*/ ) {
TQ_INT16 tmp16;
TQ_INT8 tmp8;
float out;
_file->at( _krecfile->samplesToOffset( pos ) );
if ( _krecfile->bits() == 16 ) {
*_stream >> tmp16;
out = tmp16 / 65535.0;
}
else {
*_stream >> tmp8;
out = tmp8 / 65535.0;
}
return out;
}
float* KRecBuffer::getsamples( int start, int end, int channel ) {
float* tmp = new float[ end-start ];
for ( int i=start; i<end; ++i )
tmp[ i ] = getSample( i, channel );
return tmp;
}