Commit eea6e029 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Playback the main buffer almost well

No capture for now
No dtmf, no ringtones
parent 10dadd02
This diff is collapsed.
......@@ -129,6 +129,8 @@ class AudioLayer {
*/
virtual int putUrgent(void* buffer, int toCopy) = 0;
virtual int putMain( void* buffer, int toCopy) = 0;
/**
* Query the capture device for number of bytes available in the hardware ring buffer
* @return int The number of bytes available
......
......@@ -377,8 +377,13 @@ AudioRtpRTX::receiveSessionForSpkr (int& countTime)
toAudioLayer = _dataAudioLayer;
#endif
audiolayer->playSamples(toAudioLayer, nbSample * sizeof(SFLDataFormat), true);
// int layer = audiolayer->getLayerType();
// _debug(" interface %i\n" , layer);
//#if CHECK_INTERFACE( layer , ALSA )
// audiolayer->playSamples(toAudioLayer, nbSample * sizeof(SFLDataFormat), true);
//#else
audiolayer->putMain( toAudioLayer, nbSample * sizeof(SFLDataFormat) );
//#endif
// Notify (with a beep) an incoming call when there is already a call
countTime += time->getSecond();
if (Manager::instance().incomingCallWaiting() > 0) {
......
......@@ -23,67 +23,85 @@ static pa_context *context = NULL;
static pa_stream* playback = NULL;
static pa_stream* record = NULL;
static pa_mainloop_api *mainloop_api = NULL;
static pa_sample_spec sample_spec;
static pa_threaded_mainloop *m = NULL;
static pa_sample_spec sample_spec ;
static pa_channel_map channel_map;
PulseLayer::PulseLayer(ManagerImpl* manager)
static std::string pcm_p, pcm_r;
int framesPerBuffer = 882;
PulseLayer::PulseLayer(ManagerImpl* manager)
: AudioLayer( manager , PULSEAUDIO )
, _mainSndRingBuffer( SIZEBUF )
{
_debug("Pulse audio constructor: Create context\n");
create_context();
}
// Destructor
PulseLayer::~PulseLayer (void)
{
assert(mainloop_api);
mainloop_api->quit( mainloop_api, 0 );
// pa_stream_flush();
// pa_stream_disconnect();
//mainloop_api->quit( mainloop_api, 0 );
pa_stream_flush( playback , NULL, NULL);
pa_stream_disconnect( playback );
pa_context_disconnect(context);
}
void
PulseLayer::create_context( void )
void
PulseLayer::connectPulseServer( void )
{
pa_context_flags_t flag = PA_CONTEXT_NOAUTOSPAWN ;
int ret = 1;
// Instanciate a mainloop object
pa_mainloop *m;
if(!( m=pa_mainloop_new()))
_debug("Error while creating the mainloop\n");
mainloop_api = pa_mainloop_get_api( m );
pa_threaded_mainloop_lock( m );
// Instanciate a context
if( !(context = pa_context_new( mainloop_api , "SFLphone" )))
_debug("Error while creating the context\n");
pa_context_ref( context );
_debug("Connect the context to the server\n");
pa_context_connect( context, NULL , flag , NULL );
pa_context_set_state_callback(context, context_state_callback, NULL);
pa_context_set_state_callback(context, context_state_callback, this);
pa_threaded_mainloop_wait( m );
pa_context_connect( context, NULL , flag , NULL );
// Run the main loop
pa_mainloop_run(m , &ret);
if( pa_context_get_state( context ) != PA_CONTEXT_READY ){
_debug("Error connecting to pulse audio server\n");
pa_threaded_mainloop_unlock( m );
}
pa_threaded_mainloop_unlock( m );
_debug("Context creation done\n");
}
void
void
PulseLayer::stream_state_callback( pa_stream* s, void* user_data )
{
_debug("The state of the stream changed\n");
assert(s);
switch(pa_stream_get_state(s)){
case PA_STREAM_CREATING:
case PA_STREAM_TERMINATED:
_debug("Stream is creating...\n");
break;
case PA_STREAM_READY:
_debug("Stream successfully created\n");
break;
case PA_STREAM_FAILED:
default:
_debug("Stream error: %s\n" , pa_strerror(pa_context_errno(pa_stream_get_context(s))));
break;
}
}
void
void
PulseLayer::context_state_callback( pa_context* c, void* user_data )
{
_debug("The state of the context changed\n");
sample_spec.format = PA_SAMPLE_S16LE;
sample_spec.channels = 1;
channel_map.channels = 1;
pa_stream_flags_t flag = PA_STREAM_START_CORKED ;
assert(c);
PulseLayer* pulse = (PulseLayer*)user_data;
//pa_stream_flags_t flag = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE ;
assert(c && m);
switch(pa_context_get_state(c)){
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
......@@ -93,20 +111,8 @@ PulseLayer::context_state_callback( pa_context* c, void* user_data )
case PA_CONTEXT_READY:
pa_cvolume cv;
assert(c && !playback && !record);
pulse->createStreams( c );
_debug("Connection to PulseAudio server established\n");
playback = pa_stream_new( c, "playback stream" , &sample_spec, &channel_map);
record = pa_stream_new( c, "capture stream" , &sample_spec, &channel_map);
assert(playback);
assert(record);
// Set up the parameters required to open a (Callback)Stream:
pa_stream_set_state_callback(playback, stream_state_callback, NULL);
// Transferring Data - Asynchronous Mode
pa_stream_set_write_callback(playback, audioCallback, NULL);
pa_stream_connect_playback( playback, NULL , NULL , flag , NULL, NULL );
break;
case PA_CONTEXT_TERMINATED:
_debug("Context terminated\n");
......@@ -118,70 +124,91 @@ PulseLayer::context_state_callback( pa_context* c, void* user_data )
}
}
void
PulseLayer::createStreams( pa_context* c )
{
_debug( " Create Audio Streams \n ");
//pa_stream_flags_t flag = PA_STREAM_AUTO_TIMING_UPDATE;
pa_stream_flags_t flag = PA_STREAM_FIX_RATE;
sample_spec.format = PA_SAMPLE_S16LE;
sample_spec.rate = 44100;
sample_spec.channels = 1;
channel_map.channels = 1;
if( !pa_sample_spec_valid( &sample_spec ) ){
_debug("Invalid sample specifications\n");
exit(0);
}
if(!(playback = pa_stream_new( c, "SFLphone out" , &sample_spec, &channel_map))){
_debug("Playback: pa_stream_new() failed : %s\n" , pa_strerror( pa_context_errno( c)));
exit(0);
}
if(!(record = pa_stream_new( c, "SFLphone Mic" , &sample_spec, &channel_map))){
_debug("Capture: pa_stream_new() failed : %s\n" , pa_strerror( pa_context_errno( c)));
exit(0);
}
assert(playback);
assert(record);
assert(m);
// Set up the parameters required to open a (Callback)Stream:
pa_stream_connect_playback( playback, NULL , NULL , flag , NULL, NULL );
pa_stream_set_state_callback(playback, stream_state_callback, NULL);
// Transferring Data - Asynchronous Mode
pa_stream_set_write_callback(playback, audioCallback, this);
bool
pa_threaded_mainloop_signal(m , 0);
pa_stream_set_state_callback(record, stream_state_callback, NULL);
// Transferring Data - Asynchronous Mode
pa_stream_set_read_callback(record, audioCallback, this);
pa_stream_connect_record( record, NULL , NULL , flag );
}
bool
PulseLayer::openDevice(int indexIn, int indexOut, int sampleRate, int frameSize , int stream, std::string plugin)
{
_sampleRate = sampleRate;
_frameSize = frameSize;
//sample_spec.rate = sampleRate;
//sample_spec.format = PA_SAMPLE_S16LE;
//sample_spec.channels = 1;
//channel_map.channels = 1;
//pa_stream_flags_t flag = PA_STREAM_START_CORKED ;
_debug(" Setting PulseLayer: device in=%2d, out=%2d\n", indexIn, indexOut);
_debug(" : nb channel in=%2d, out=%2d\n", _inChannel, _outChannel);
_debug(" : sample rate=%5d\n", _sampleRate );
/*
assert(context);
switch(pa_context_get_state(context)){
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
_debug("Waiting....\n");
break;
case PA_CONTEXT_READY:
pa_cvolume cv;
assert(context && !playback && !record);
_debug("Connection to PulseAudio server established\n");
playback = pa_stream_new( context, "playback stream" , &sample_spec, &channel_map);
record = pa_stream_new( context, "capture stream" , &sample_spec, &channel_map);
m = pa_threaded_mainloop_new();
assert(m);
assert(playback);
assert(record);
if( pa_threaded_mainloop_start( m ) < 0 ){
_debug("Failed starting the mainloop\n");
}
// Set up the parameters required to open a (Callback)Stream:
// Instanciate a context
if( !(context = pa_context_new( pa_threaded_mainloop_get_api( m ) , "SFLphone" )))
_debug("Error while creating the context\n");
pa_stream_set_state_callback(playback, stream_state_callback, NULL);
// Transferring Data - Asynchronous Mode
pa_stream_set_write_callback(playback, audioCallback, NULL);
pa_stream_connect_playback( playback, NULL , NULL , flag , NULL, NULL );
assert(context);
break;
case PA_CONTEXT_TERMINATED:
_debug("Context terminated\n");
break;
case PA_CONTEXT_FAILED:
default:
_debug(" Error : %s" , pa_strerror(pa_context_errno(context)));
exit(1);
}*/
connectPulseServer();
_debug("Connection Done!! \n");
}
void
void
PulseLayer::closeCaptureStream( void )
{
}
void
void
PulseLayer::closePlaybackStream( void )
{
}
int
int
PulseLayer::playSamples(void* buffer, int toCopy, bool isTalking)
{
}
......@@ -189,6 +216,15 @@ PulseLayer::playSamples(void* buffer, int toCopy, bool isTalking)
int
PulseLayer::putMain(void* buffer, int toCopy)
{
int a = _mainSndRingBuffer.AvailForPut();
if ( a >= toCopy ) {
return _mainSndRingBuffer.Put(buffer, toCopy, 100);
} else {
_debug("Chopping sound, Ouch! RingBuffer full ?\n");
return _mainSndRingBuffer.Put(buffer, a, 100);
}
return 0;
}
void
......@@ -204,11 +240,13 @@ PulseLayer::putUrgent(void* buffer, int toCopy)
int
PulseLayer::canGetMic()
{
return 882;
}
int
PulseLayer::getMic(void *buffer, int toCopy)
{
return 160;
}
void
......@@ -221,29 +259,89 @@ PulseLayer::isStreamStopped (void)
{
}
void
void
PulseLayer::startStream (void)
{
_debug("Start stream\n");
//pa_stream_cork( playback , 0, NULL, NULL);
}
void
void
PulseLayer::stopStream (void)
{
_debug("Stop stream\n");
pa_stream_drop( playback );
}
bool
bool
PulseLayer::isStreamActive (void)
{
}
void
PulseLayer::audioCallback ( pa_stream* s, size_t bytes, void* user_data )
PulseLayer::audioCallback ( pa_stream* s, size_t bytes, void* userdata )
{
_debug("Audio callback: New data may be written to the stream\n");
pa_threaded_mainloop_signal( m , 0);
assert( s && bytes );
PulseLayer* pulse = (PulseLayer*) userdata;
pulse->write();
//if(pa_stream_get_state(s) == PA_STREAM_READY )
//{
//if( bytes > 0 ){
// pa_stream_write( s, user_data, bytes, pa_xfree, 0, PA_SEEK_RELATIVE );
//}
//}
// pa_stream_write
// pa_stream_peek ( to read the next fragment from the buffer ) / pa_stream_drop( to remove the data from the buffer )
// // pa_stream_peek ( to read the next fragment from the buffer ) / pa_stream_drop( to remove the data from the buffer )
//
// int toPut;
// int urgentAvail; // number of data right and data left
// int micAvailPut;
//
// // AvailForGet tell the number of chars inside the buffer
// // framePerBuffer are the number of data for one channel (left)
// urgentAvail = _urgentRingBuffer.AvailForGet();
// if (urgentAvail > 0) {
// // Urgent data (dtmf, incoming call signal) come first.
// toGet = (urgentAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? urgentAvail : framesPerBuffer * sizeof(SFLDataFormat);
// _urgentRingBuffer.Get(out, toGet, spkrVolume);
// // Consume the regular one as well (same amount of bytes)
// _mainSndRingBuffer.Discard(toGet);
// } else {
// AudioLoop* tone = _manager->getTelephoneTone();
// if ( tone != 0) {
// tone->getNext(out, framesPerBuffer, spkrVolume);
// } else if ( (tone=_manager->getTelephoneFile()) != 0 ) {
// tone->getNext(out, framesPerBuffer, spkrVolume);
// } else {
// }
// }
//
// // Additionally handle the mic's audio stream
// micAvailPut = _micRingBuffer.AvailForPut();
// toPut = (micAvailPut <= (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? micAvailPut : framesPerBuffer * sizeof(SFLDataFormat);
// //_debug("AL: Nb sample: %d char, [0]=%f [1]=%f [2]=%f\n", toPut, in[0], in[1], in[2]);
// _micRingBuffer.Put(in, toPut, micVolume);
}
void
PulseLayer::write( void )
{
int toGet;
int normalAvail; // number of data right and data left
SFLDataFormat* out = (SFLDataFormat*)malloc(framesPerBuffer * sizeof(SFLDataFormat));
normalAvail = _mainSndRingBuffer.AvailForGet();
toGet = (normalAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof(SFLDataFormat);
if (toGet) {
_mainSndRingBuffer.Get(out, toGet, 100);
_debug("Write %i bytes\n" , toGet);
pa_stream_write( playback , out , toGet , pa_xfree, 0 , PA_SEEK_RELATIVE);
_mainSndRingBuffer.Discard(toGet);
} else {
bzero(out, framesPerBuffer * sizeof(SFLDataFormat));
}
}
......@@ -74,7 +74,7 @@ class PulseLayer : public AudioLayer {
*/
int playSamples(void* buffer, int toCopy, bool isTalking) ;
static void audioCallback ( pa_stream* s, size_t bytes, void* user_data );
static void audioCallback ( pa_stream* s, size_t bytes, void* userdata );
static void stream_state_callback( pa_stream* s, void* user_data );
static void context_state_callback( pa_context* c, void* user_data );
......@@ -123,12 +123,16 @@ class PulseLayer : public AudioLayer {
*/
void closeCaptureStream( void );
void write( void );
void createStreams( pa_context* c );
/**
* Drop the pending frames and close the playback device
*/
void closePlaybackStream( void );
void create_context( void );
void connectPulseServer( void );
RingBuffer _mainSndRingBuffer;
//pa_stream* playback;
//pa_stream* record;
......
......@@ -715,8 +715,14 @@ ManagerImpl::playATone(Tone::TONEID toneId) {
unsigned int nbSampling = audioloop->getSize();
AudioLayer* audiolayer = getAudioDriver();
SFLDataFormat buf[nbSampling];
if ( audiolayer ) {
if ( audiolayer ) {
int layer = audiolayer->getLayerType();
#if CHECK_INTERFACE( layer , ALSA )
audiolayer->putUrgent( buf, nbSampling );
#else
// Pulseaudio code
// startStream()?;
#endif
}
else
return false;
......@@ -734,7 +740,11 @@ ManagerImpl::stopTone(bool stopAudio=true) {
if (stopAudio) {
AudioLayer* audiolayer = getAudioDriver();
//if (audiolayer) { audiolayer->stopStream(); }
int layer = audiolayer->getLayerType();
#if CHECK_INTERFACE( layer , ALSA )
#else
//if (audiolayer) { audiolayer->stopStream(); }
#endif
}
_toneMutex.enterMutex();
......@@ -799,6 +809,7 @@ ManagerImpl::ringtone()
}
AudioLayer* audiolayer = getAudioDriver();
int layer = audiolayer->getLayerType();
if (audiolayer==0) { return; }
int sampleRate = audiolayer->getSampleRate();
AudioCodec* codecForTone = _codecDescriptorMap.getFirstCodecAvailable();
......@@ -810,10 +821,15 @@ ManagerImpl::ringtone()
_toneMutex.enterMutex();
_audiofile.start();
_toneMutex.leaveMutex();
#if CHECK_INTERFACE( layer, ALSA )
int size = _audiofile.getSize();
SFLDataFormat output[ size ];
_audiofile.getNext(output, size , 100);
audiolayer->putUrgent( output , size );
#else
// pulseaudio code
startStream();
#endif
} else {
ringback();
}
......@@ -852,6 +868,7 @@ ManagerImpl::notificationIncomingCall(void) {
AudioLayer* audiolayer = getAudioDriver();
if (audiolayer != 0) {
int layer = audiolayer->getLayerType();
unsigned int samplerate = audiolayer->getSampleRate();
std::ostringstream frequency;
frequency << "440/" << FRAME_PER_BUFFER;
......@@ -860,7 +877,11 @@ ManagerImpl::notificationIncomingCall(void) {
unsigned int nbSampling = tone.getSize();
SFLDataFormat buf[nbSampling];
tone.getNext(buf, tone.getSize());
#if CHECK_INTERFACE( layer , ALSA )
audiolayer->playSamples(buf, sizeof(SFLDataFormat)*nbSampling, true);
#else
audiolayer->putUrgent( buf, sizeof(SFLDataFormat)*nbSampling );
#endif
}
}
......@@ -1158,6 +1179,8 @@ ManagerImpl::getOutputAudioPluginList(void)
void
ManagerImpl::setInputAudioPlugin(const std::string& audioPlugin)
{
int layer = _audiodriver -> getLayerType();
#if CHECK_INTERFACE( layer , ALSA )
_debug("Set input audio plugin\n");
_audiodriver -> setErrorMessage( -1 );
_audiodriver -> openDevice( _audiodriver -> getIndexIn(),
......@@ -1168,6 +1191,8 @@ ManagerImpl::setInputAudioPlugin(const std::string& audioPlugin)
audioPlugin);
if( _audiodriver -> getErrorMessage() != -1)
notifyErrClient( _audiodriver -> getErrorMessage() );
#else
#endif
}
/**
......@@ -1176,6 +1201,8 @@ ManagerImpl::setInputAudioPlugin(const std::string& audioPlugin)
void
ManagerImpl::setOutputAudioPlugin(const std::string& audioPlugin)
{
int layer = _audiodriver -> getLayerType();
#if CHECK_INTERFACE( layer , ALSA )
_debug("Set output audio plugin\n");
_audiodriver -> setErrorMessage( -1 );
_audiodriver -> openDevice( _audiodriver -> getIndexIn(),
......@@ -1188,6 +1215,8 @@ ManagerImpl::setOutputAudioPlugin(const std::string& audioPlugin)
notifyErrClient( _audiodriver -> getErrorMessage() );
// set config
setConfig( AUDIO , ALSA_PLUGIN , audioPlugin );
#else
#endif
}
/**
......@@ -1206,6 +1235,8 @@ ManagerImpl::getAudioOutputDeviceList(void)
void
ManagerImpl::setAudioOutputDevice(const int index)
{
int layer = _audiodriver -> getLayerType();
#if CHECK_INTERFACE( layer , ALSA )
_debug("Set audio output device: %i\n", index);
_audiodriver -> setErrorMessage( -1 );
_audiodriver->openDevice(_audiodriver->getIndexIn(),
......@@ -1218,6 +1249,8 @@ ManagerImpl::setAudioOutputDevice(const int index)
notifyErrClient( _audiodriver -> getErrorMessage() );
// set config
setConfig( AUDIO , ALSA_CARD_ID_OUT , index );
#else
#endif
}
/**
......@@ -1236,6 +1269,8 @@ ManagerImpl::getAudioInputDeviceList(void)
void
ManagerImpl::setAudioInputDevice(const int index)
{
int layer = _audiodriver -> getLayerType();
#if CHECK_INTERFACE( layer , ALSA )
_debug("Set audio input device %i\n", index);
_audiodriver -> setErrorMessage( -1 );
_audiodriver->openDevice(index,
......@@ -1248,6 +1283,8 @@ ManagerImpl::setAudioInputDevice(const int index)
notifyErrClient( _audiodriver -> getErrorMessage() );
// set config
setConfig( AUDIO , ALSA_CARD_ID_IN , index );
#else
#endif
}
/**
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment