00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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>
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
00091
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
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
00225 QByteArray * bytearray = new QByteArray( size );
00226
00227
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
00237 emit data( *bytearray );
00238
00239 delete bytearray;
00240 }
00241 }
00242
00244
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
00262 emit data( (char *)inpacket->contents, inpacket->size );
00263 inpacket->processed();
00264 }
00265
00266
00267
00268 #include "kaudiorecordstream.moc"
00269 #include "kaudiorecordstream_p.moc"