/*************************************************************************** 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 #include #include #include #include #include #include #include #include #include #include #include #include #include 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( 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; isetGroup( "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::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= 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, TQ_SIGNAL( posChanged( KRecBuffer*, TQIODevice::Offset ) ), this, TQ_SLOT( newPos( KRecBuffer*, TQIODevice::Offset ) ) ); connect( buffer, TQ_SIGNAL( sizeChanged( KRecBuffer*, TQIODevice::Offset ) ), this, TQ_SLOT( newSize( KRecBuffer*, TQIODevice::Offset ) ) ); connect( buffer, TQ_SIGNAL( deleteSelf( KRecBuffer* ) ), this, TQ_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::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; iatEnd() ) 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