/* Copyright (C) 2001, 2002 Matthias Kretz kretz@kde.org 2003 Arnold Krille arnold@arnoldarts.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kaudiorecordstream.h" #include "kaudiorecordstream_p.h" #include "kartsserver.h" #include #include #include #include #include #include #include //QByteArray #include struct KAudioRecordStream::Data { Arts::Synth_AMAN_RECORD in; Arts::AudioToByteStream convert; Arts::StereoEffectStack effectStack; Arts::ByteSoundReceiver receiver; KByteSoundReceiver * receiver_base; KArtsServer * kserver; bool attached; bool blocking; bool polling; unsigned int pos; TQPtrQueue inqueue; TQString title; }; KAudioRecordStream::KAudioRecordStream( KArtsServer * kserver, const TQString & title, TQObject * parent, const char * name ) : TQObject( parent, name ) , d( new Data ) { d->kserver = kserver; d->attached = false; d->blocking = true; d->polling = false; d->pos = 0; d->inqueue.setAutoDelete( true ); d->title = title; connect( d->kserver, TQT_SIGNAL( restartedServer() ), TQT_SLOT( slotRestartedServer() ) ); d->in = Arts::DynamicCast( d->kserver->server().createObject( "Arts::Synth_AMAN_RECORD" ) ); d->effectStack = Arts::DynamicCast( d->kserver->server().createObject( "Arts::StereoEffectStack" ) ); d->convert = Arts::DynamicCast( d->kserver->server().createObject( "Arts::AudioToByteStream" ) ); if( d->in.isNull() ) kdFatal( 400 ) << "couldn't create a Synth_AMAN_RECORD on the aRts server\n"; if( d->effectStack.isNull() ) kdFatal( 400 ) << "couldn't create a StereoEffectStack on the aRts server\n"; if( d->convert.isNull() ) kdFatal( 400 ) << "couldn't create a AudioToByteStream on the aRts server\n"; d->in.title( ( const char * ) d->title.local8Bit() ); Arts::connect( d->in, d->effectStack ); d->in.start(); d->effectStack.start(); } KAudioRecordStream::~KAudioRecordStream() { d->receiver = Arts::ByteSoundReceiver::null(); // don't delete receiver_base because aRts takes care of that (in the line // above) d->receiver_base = 0; delete d; } int KAudioRecordStream::read( char * buffer, int size ) { kdDebug( 400 ) << k_funcinfo << endl; unsigned int remaining = size; while( remaining ) { if( d->blocking ) while( d->inqueue.isEmpty() ) Arts::Dispatcher::the()->ioManager()->processOneEvent( true ); else { if( d->inqueue.isEmpty() ) Arts::Dispatcher::the()->ioManager()->processOneEvent( false ); if( d->inqueue.isEmpty() ) return size - remaining; } TQByteArray * data = d->inqueue.head(); unsigned int tocopy = kMin( remaining, data->size() - d->pos ); memcpy( buffer, data->data() + d->pos, tocopy ); d->pos += tocopy; buffer += tocopy; remaining -= tocopy; if( d->pos == data->size() ) { d->inqueue.remove(); d->pos = 0; } } return size; } void KAudioRecordStream::setBlockingIO( bool blocking ) { d->blocking = blocking; } bool KAudioRecordStream::blockingIO() const { return d->blocking; } void KAudioRecordStream::usePolling( bool polling ) { d->polling = polling; if( ! polling ) flush(); } bool KAudioRecordStream::polling() const { return d->polling; } Arts::StereoEffectStack KAudioRecordStream::effectStack() const { return d->effectStack; } bool KAudioRecordStream::running() const { return d->attached; } void KAudioRecordStream::stop() { kdDebug( 400 ) << k_funcinfo << endl; if( d->attached ) { d->receiver.stop(); d->convert.stop(); Arts::disconnect( d->convert, d->receiver ); d->receiver = Arts::ByteSoundReceiver::null(); d->receiver_base = 0; Arts::disconnect( d->effectStack, d->convert ); d->attached = false; emit running( false ); } } void KAudioRecordStream::start( int samplingRate, int bits, int channels ) { kdDebug( 400 ) << k_funcinfo << "samplingRate: " << samplingRate << " bits: " << bits << " channels: " << channels << endl; if( ! d->attached ) { assert( d->kserver ); if( ( samplingRate < 500 || samplingRate > 2000000 ) || ( channels != 1 && channels != 2 ) || ( bits != 8 && bits != 16 ) ) { kdWarning( 400 ) << "invalid stream parameters: rate=" << samplingRate << ", " << bits << " bit, " << channels << " channels\n"; } else { d->convert.samplingRate( samplingRate ); d->convert.channels( channels ); d->convert.bits( bits ); Arts::connect( d->effectStack, d->convert ); d->receiver_base = new KByteSoundReceiver( samplingRate, bits, channels, d->title.local8Bit() ); d->receiver = Arts::ByteSoundReceiver::_from_base( d->receiver_base ); connect( d->receiver_base, TQT_SIGNAL( data( const char *, unsigned int ) ), TQT_SLOT( slotData( const char *, unsigned int ) ) ); Arts::connect( d->convert, "outdata", d->receiver, "indata" ); d->convert.start(); d->receiver.start(); //### needed? Arts::Dispatcher::the()->ioManager()->processOneEvent( false ); d->attached = true; emit running( true ); } } } void KAudioRecordStream::flush() { kdDebug( 400 ) << k_funcinfo << endl; d->inqueue.clear(); } void KAudioRecordStream::slotRestartedServer() { } void KAudioRecordStream::slotData( const char * contents, unsigned int size ) { //kdDebug( 400 ) << k_funcinfo << endl; TQByteArray * bytearray = new TQByteArray( size ); // copy the contents to the bytearray // this has to be deleted later bytearray->duplicate( contents, size ); if( d->polling ) { kdDebug( 400 ) << "enqueue the data\n"; d->inqueue.enqueue( bytearray ); } else { //kdDebug( 400 ) << "emit the data\n"; emit data( *bytearray ); //kdDebug( 400 ) << "delete the data\n"; delete bytearray; } } //////////////////////////////////////// // ---*--- KByteSoundReceiver ---*--- // //////////////////////////////////////// KByteSoundReceiver::KByteSoundReceiver( int rate, int bits, int channels, const char * title ) : _samplingRate( rate ) , _bits( bits ) , _channels( channels ) , _title( title ) { } KByteSoundReceiver::~KByteSoundReceiver() { } void KByteSoundReceiver::process_indata( Arts::DataPacket * inpacket ) { //kdDebug( 400 ) << k_funcinfo << " size of the packet: " << inpacket->size << endl; emit data( (char *)inpacket->contents, inpacket->size ); inpacket->processed(); } #include "kaudiorecordstream.moc" #include "kaudiorecordstream_p.moc"