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"