kaudiorecordstream.cpp

00001     /*
00002 
00003     Copyright (C) 2001, 2002 Matthias Kretz
00004                             kretz@kde.org
00005                   2003       Arnold Krille
00006                              arnold@arnoldarts.de
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012   
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 
00023     */
00024 
00025 #include "kaudiorecordstream.h"
00026 #include "kaudiorecordstream_p.h"
00027 #include "kartsserver.h"
00028 
00029 #include <artsflow.h>
00030 #include <soundserver.h>
00031 
00032 #include <kglobal.h>
00033 #include <kdebug.h>
00034 
00035 #include <qstring.h>
00036 #include <qptrqueue.h>
00037 #include <qcstring.h> //QByteArray
00038 
00039 #include <assert.h>
00040 
00041 struct KAudioRecordStream::Data
00042 {
00043     Arts::Synth_AMAN_RECORD in;
00044     Arts::AudioToByteStream convert;
00045     Arts::StereoEffectStack effectStack;
00046     Arts::ByteSoundReceiver receiver;
00047     KByteSoundReceiver * receiver_base;
00048     KArtsServer * kserver;
00049     bool attached;
00050     bool blocking;
00051     bool polling;
00052     unsigned int pos;
00053     QPtrQueue<QByteArray> inqueue;
00054     QString title;
00055 };
00056 
00057 KAudioRecordStream::KAudioRecordStream( KArtsServer * kserver, const QString & title, QObject * parent, const char * name )
00058     : QObject( parent, name )
00059     , d( new Data )
00060 {
00061     d->kserver = kserver;
00062     d->attached = false;
00063     d->blocking = true;
00064     d->polling = false;
00065     d->pos = 0;
00066     d->inqueue.setAutoDelete( true );
00067     d->title = title;
00068 
00069     connect( d->kserver, SIGNAL( restartedServer() ), SLOT( slotRestartedServer() ) );
00070 
00071     d->in = Arts::DynamicCast( d->kserver->server().createObject( "Arts::Synth_AMAN_RECORD" ) );
00072     d->effectStack = Arts::DynamicCast( d->kserver->server().createObject( "Arts::StereoEffectStack" ) );
00073     d->convert = Arts::DynamicCast( d->kserver->server().createObject( "Arts::AudioToByteStream" ) );
00074     if( d->in.isNull() )
00075         kdFatal( 400 ) << "couldn't create a Synth_AMAN_RECORD on the aRts server\n";
00076     if( d->effectStack.isNull() )
00077         kdFatal( 400 ) << "couldn't create a StereoEffectStack on the aRts server\n";
00078     if( d->convert.isNull() )
00079         kdFatal( 400 ) << "couldn't create a AudioToByteStream on the aRts server\n";
00080 
00081     d->in.title( ( const char * ) d->title.local8Bit() );
00082     Arts::connect( d->in, d->effectStack );
00083     d->in.start();
00084     d->effectStack.start();
00085 }
00086 
00087 KAudioRecordStream::~KAudioRecordStream()
00088 {
00089     d->receiver = Arts::ByteSoundReceiver::null();
00090     // don't delete receiver_base because aRts takes care of that (in the line
00091     // above)
00092     d->receiver_base = 0;
00093     delete d;
00094 }
00095 
00096 int KAudioRecordStream::read( char * buffer, int size )
00097 {
00098     kdDebug( 400 ) << k_funcinfo << endl;
00099     unsigned int remaining = size;
00100     while( remaining )
00101     {
00102         if( d->blocking )
00103             while( d->inqueue.isEmpty() )
00104                 Arts::Dispatcher::the()->ioManager()->processOneEvent( true );
00105         else
00106         {
00107             if( d->inqueue.isEmpty() )
00108                 Arts::Dispatcher::the()->ioManager()->processOneEvent( false );
00109             if( d->inqueue.isEmpty() )
00110                 return size - remaining;
00111         }
00112         QByteArray * data = d->inqueue.head();
00113         unsigned int tocopy = kMin( remaining, data->size() - d->pos );
00114         memcpy( buffer, data->data() + d->pos, tocopy );
00115         d->pos += tocopy;
00116         buffer += tocopy;
00117         remaining -= tocopy;
00118         if( d->pos == data->size() )
00119         {
00120             d->inqueue.remove();
00121             d->pos = 0;
00122         }
00123     }
00124     return size;
00125 }
00126 
00127 void KAudioRecordStream::setBlockingIO( bool blocking )
00128 {
00129     d->blocking = blocking;
00130 }
00131 
00132 bool KAudioRecordStream::blockingIO() const
00133 {
00134     return d->blocking;
00135 }
00136 
00137 void KAudioRecordStream::usePolling( bool polling )
00138 {
00139     d->polling = polling;
00140     if( ! polling )
00141         flush();
00142 }
00143 
00144 bool KAudioRecordStream::polling() const
00145 {
00146     return d->polling;
00147 }
00148 
00149 Arts::StereoEffectStack KAudioRecordStream::effectStack() const
00150 {
00151     return d->effectStack;
00152 }
00153 
00154 bool KAudioRecordStream::running() const
00155 {
00156     return d->attached;
00157 }
00158 
00159 void KAudioRecordStream::stop()
00160 {
00161     kdDebug( 400 ) << k_funcinfo << endl;
00162     if( d->attached )
00163     {
00164         d->receiver.stop();
00165         d->convert.stop();
00166 
00167         Arts::disconnect( d->convert, d->receiver );
00168         d->receiver = Arts::ByteSoundReceiver::null();
00169         d->receiver_base = 0;
00170 
00171         Arts::disconnect( d->effectStack, d->convert );
00172 
00173         d->attached = false;
00174         emit running( false );
00175     }
00176 }
00177 
00178 void KAudioRecordStream::start( int samplingRate, int bits, int channels )
00179 {
00180     kdDebug( 400 ) << k_funcinfo << "samplingRate: " << samplingRate << " bits: " << bits << " channels: " << channels << endl;
00181     if( ! d->attached )
00182     {
00183         assert( d->kserver );
00184 
00185         if( ( samplingRate < 500 || samplingRate > 2000000 )
00186                 || ( channels != 1 && channels != 2 ) || ( bits != 8 && bits != 16 ) )
00187         {
00188             kdWarning( 400 ) << "invalid stream parameters: rate=" << samplingRate << ", " << bits << " bit, " << channels << " channels\n";
00189         }
00190         else
00191         {
00192             d->convert.samplingRate( samplingRate );
00193             d->convert.channels( channels );
00194             d->convert.bits( bits );
00195             Arts::connect( d->effectStack, d->convert );
00196 
00197             d->receiver_base = new KByteSoundReceiver( samplingRate, bits, channels, d->title.local8Bit() );
00198             d->receiver = Arts::ByteSoundReceiver::_from_base( d->receiver_base );
00199             connect( d->receiver_base, SIGNAL( data( const char *, unsigned int ) ),
00200                     SLOT( slotData( const char *, unsigned int ) ) );
00201             Arts::connect( d->convert, "outdata", d->receiver, "indata" );
00202 
00203             d->convert.start();
00204             d->receiver.start();
00205 
00206             //### needed?
00207             Arts::Dispatcher::the()->ioManager()->processOneEvent( false );
00208             d->attached = true;
00209             emit running( true );
00210         }
00211     }
00212 }
00213 
00214 void KAudioRecordStream::flush()
00215 {
00216     kdDebug( 400 ) << k_funcinfo << endl;
00217     d->inqueue.clear();
00218 }
00219 
00220 void KAudioRecordStream::slotRestartedServer() { }
00221 
00222 void KAudioRecordStream::slotData( const char * contents, unsigned int size )
00223 {
00224     //kdDebug( 400 ) << k_funcinfo << endl;
00225     QByteArray * bytearray = new QByteArray( size );
00226     // copy the contents to the bytearray
00227     // this has to be deleted later
00228     bytearray->duplicate( contents, size );
00229     if( d->polling )
00230     {
00231         kdDebug( 400 ) << "enqueue the data\n";
00232         d->inqueue.enqueue( bytearray );
00233     }
00234     else
00235     {
00236         //kdDebug( 400 ) << "emit the data\n";
00237         emit data( *bytearray );
00238         //kdDebug( 400 ) << "delete the data\n";
00239         delete bytearray;
00240     }
00241 }
00242 
00244 // ---*--- KByteSoundReceiver ---*--- //
00246 
00247 KByteSoundReceiver::KByteSoundReceiver( int rate, int bits, int channels, const char * title )
00248     : _samplingRate( rate )
00249     , _bits( bits )
00250     , _channels( channels )
00251     , _title( title )
00252 {
00253 }
00254 
00255 KByteSoundReceiver::~KByteSoundReceiver()
00256 {
00257 }
00258 
00259 void KByteSoundReceiver::process_indata( Arts::DataPacket<Arts::mcopbyte> * inpacket )
00260 {
00261     //kdDebug( 400 ) << k_funcinfo << " size of the packet: " << inpacket->size << endl;
00262     emit data( (char *)inpacket->contents, inpacket->size );
00263     inpacket->processed();
00264 }
00265 
00266 // vim:sw=4:ts=4
00267 
00268 #include "kaudiorecordstream.moc"
00269 #include "kaudiorecordstream_p.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys