/*
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 <artsflow.h>
# include <soundserver.h>
# include <tdeglobal.h>
# include <kdebug.h>
# include <tqstring.h>
# include <tqptrqueue.h>
# include <tqcstring.h> //QByteArray
# include <assert.h>
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 < TQByteArray > 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 < Arts : : mcopbyte > * inpacket )
{
//kdDebug( 400 ) << k_funcinfo << " size of the packet: " << inpacket->size << endl;
emit data ( ( char * ) inpacket - > contents , inpacket - > size ) ;
inpacket - > processed ( ) ;
}
// vim:sw=4:ts=4
# include "kaudiorecordstream.moc"
# include "kaudiorecordstream_p.moc"