Skip to content
Snippets Groups Projects
Commit 6154e940 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Functionnal playback and capture

parent e2946414
No related branches found
No related tags found
No related merge requests found
......@@ -19,12 +19,12 @@
#include "pulselayer.h"
static pa_channel_map channel_map ;
static pa_stream_flags_t flag;
static pa_sample_spec sample_spec ;
static pa_volume_t volume;
int framesPerBuffer = 4096;
/*static pa_channel_map channel_map ;
static pa_stream_flags_t flag;
static pa_sample_spec sample_spec ;
static pa_volume_t volume;
*/
int framesPerBuffer = 2048;
const pa_buffer_attr *a;
PulseLayer::PulseLayer(ManagerImpl* manager)
......@@ -39,7 +39,8 @@ const pa_buffer_attr *a;
// Destructor
PulseLayer::~PulseLayer (void)
{
////delete cache;
delete playback;
delete record;
pa_context_disconnect(context);
}
......@@ -94,67 +95,18 @@ void PulseLayer::context_state_callback( pa_context* c, void* user_data )
}
}
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
PulseLayer::createStreams( pa_context* c )
{
_debug("Creating streams...\n");
sample_spec.format = PA_SAMPLE_S16LE;
sample_spec.rate = 44100;
sample_spec.channels = 1;
channel_map.channels = 1;
flag = PA_STREAM_AUTO_TIMING_UPDATE ;
volume = PA_VOLUME_NORM;
pa_cvolume cv;
assert(pa_sample_spec_valid(&sample_spec));
assert(pa_channel_map_valid(&channel_map));
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)));
assert( playback );
pa_stream_set_write_callback( playback , audioCallback, this);
pa_stream_connect_playback( playback , NULL , NULL ,
PA_STREAM_INTERPOLATE_TIMING,
pa_cvolume_set(&cv, sample_spec.channels , volume) , NULL );
if( !( record = pa_stream_new( c, "SFLphone IN" , &sample_spec, &channel_map ) ) )
_debug("Record: pa_stream_new() failed : %s\n" , pa_strerror( pa_context_errno( c)));
assert( record );
pa_stream_connect_record( record , NULL , NULL , PA_STREAM_INTERPOLATE_TIMING );
pa_stream_set_state_callback( record , stream_state_callback, NULL);
pa_stream_set_state_callback( playback , stream_state_callback, NULL);
//playback = new AudioStream(c, PLAYBACK_STREAM, "SFLphone out");
pa_stream_set_overflow_callback( playback , overflow , this);
//record = new AudioStream(c, CAPTURE_STREAM, "SFLphone in");
pa_stream_set_read_callback( record , audioCallback, this);
pa_stream_set_underflow_callback( record , underflow , this);
playback = new AudioStream(c, PLAYBACK_STREAM, "SFLphone out");
pa_stream_set_write_callback( playback->pulseStream() , audioCallback, this);
//pa_stream_set_overflow_callback( playback , overflow , this);
record = new AudioStream(c, CAPTURE_STREAM, "SFLphone in");
pa_stream_set_read_callback( record->pulseStream() , audioCallback, this);
//pa_stream_set_underflow_callback( record , underflow , this);
//cache = new AudioStream(c, UPLOAD_STREAM, "Cache samples");
pa_threaded_mainloop_signal(m , 0);
}
bool
......@@ -235,13 +187,7 @@ PulseLayer::putUrgent(void* buffer, int toCopy)
PulseLayer::canGetMic()
{
if( record )
{
//int a = _micRingBuffer.AvailForGet();
//return a;
int a = pa_stream_readable_size( record );
_debug("available: %i\n" , a);
return 2048;
}
return _micRingBuffer.AvailForGet();
else
return 0;
}
......@@ -250,8 +196,7 @@ PulseLayer::canGetMic()
PulseLayer::getMic(void *buffer, int toCopy)
{
if( record ){
//return _micRingBuffer.Get(buffer, toCopy, 100);
return readbuffer( buffer, toCopy );
return _micRingBuffer.Get(buffer, toCopy, 100);
}
else
return 0;
......@@ -263,24 +208,23 @@ PulseLayer::flushMic()
_micRingBuffer.flush();
}
/* bool
PulseLayer::isStreamStopped (void)
{
}
*/
void
PulseLayer::startStream (void)
{
_micRingBuffer.flush();
_debug("Start stream\n");
//pa_stream_cork( record, NULL, NULL, NULL);
//pa_stream_cork( playback, NULL, NULL, NULL);
pa_threaded_mainloop_lock(m);
pa_stream_cork( record->pulseStream(), NULL, NULL, NULL);
pa_threaded_mainloop_unlock(m);
}
void
PulseLayer::stopStream (void)
{
_debug("Stop stream\n");
//pa_stream_drop( playback );
pa_stream_flush( playback->pulseStream(), NULL, NULL );
pa_stream_flush( record->pulseStream(), NULL, NULL );
flushMic();
}
bool
......@@ -294,8 +238,7 @@ PulseLayer::audioCallback ( pa_stream* s, size_t bytes, void* userdata )
PulseLayer* pulse = (PulseLayer*) userdata;
assert( s && bytes );
assert( bytes > 0 );
pulse->write();
//pulse->read();
pulse->processData();
}
void
......@@ -312,15 +255,32 @@ PulseLayer::overflow ( pa_stream* s, void* userdata )
}
void
PulseLayer::write( void )
PulseLayer::processData( void )
{
// a = pa_stream_get_buffer_attr(record->pulseStream());
//if (a)
//_debug("Buffer attributes: maxlength=%u , fragsize=%u\n" , a->maxlength, a->fragsize );
//_debug("Device name = %s ; device index = %i\n" , pa_stream_get_device_name( playback->pulseStream()) , pa_stream_get_device_index( playback->pulseStream()));
const char* data;
size_t r;
int toGet;
int urgentAvail; // number of data right and data left
int normalAvail; // number of data right and data left
// Handle the mic also
if( (record->pulseStream()) && pa_stream_get_state( record->pulseStream()) == PA_STREAM_READY) {
if( pa_stream_peek( record->pulseStream() , (const void**)&data , &r ) < 0 || !data ){
_debug("pa_stream_peek() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
return;
}
if( data != 0 ){
_micRingBuffer.Put( (void*)data , r, 100);
}
if( pa_stream_drop( record->pulseStream() ) < 0 ) {
_debug("pa_stream_drop() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
return;
}
}
SFLDataFormat* out = (SFLDataFormat*)pa_xmalloc(framesPerBuffer * sizeof(SFLDataFormat));
urgentAvail = _urgentRingBuffer.AvailForGet();
if (urgentAvail > 0) {
......@@ -352,36 +312,7 @@ PulseLayer::write( void )
}
}
}
pa_stream_write( playback , out , toGet , pa_xfree, 0 , PA_SEEK_RELATIVE);
}
void
PulseLayer::read( void )
{
if( (record) && pa_stream_get_state( record) == PA_STREAM_READY) {
size_t n = pa_stream_readable_size( record);
if( n == (size_t) -1 ){
_debug("pa_stream_readable_size(): %s\n" , pa_strerror( pa_context_errno( context )) );
return;
}
const char* data;
size_t r;
/*if( pa_stream_peek( record , (const void**)&data , &r ) < 0 || !data ){
_debug("pa_stream_peek() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
return;
}
_micRingBuffer.Put( (void*)data , r, 100);
if( pa_stream_drop( record ) < 0 ) {
_debug("pa_stream_drop() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
return;
}*/
}
pa_stream_write( playback->pulseStream() , out , toGet , pa_xfree, 0 , PA_SEEK_RELATIVE);
}
int
......@@ -392,20 +323,3 @@ PulseLayer::putInCache( char code, void *buffer, int toCopy )
//pa_stream_finish_upload( cache->pulseStream() );
}
int
PulseLayer::readbuffer( void* data , int bytes )
{
if( (record) && pa_stream_get_state( record) == PA_STREAM_READY) {
size_t r = (size_t) bytes;
if( pa_stream_peek( record , (const void**)&data , &r ) < 0 || !data ){
_debug("pa_stream_peek() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
return 0;
if( pa_stream_drop( record ) < 0 ) {
_debug("pa_stream_drop() failed: %s\n" , pa_strerror( pa_context_errno( context) ));
return 0;
}
}
return bytes;
}
}
......@@ -21,7 +21,7 @@
#define _PULSE_LAYER_H
#include "audiolayer.h"
//#include "audiostream.h"
#include "audiostream.h"
class RingBuffer;
class ManagerImpl;
......@@ -126,9 +126,7 @@ class PulseLayer : public AudioLayer {
*/
void closeCaptureStream( void );
void write( void );
void read( void );
int readbuffer( void* data, int bytes );
void processData( void );
void createStreams( pa_context* c );
/**
* Drop the pending frames and close the playback device
......@@ -146,12 +144,12 @@ class PulseLayer : public AudioLayer {
pa_context* context;
pa_threaded_mainloop* m;
//AudioStream* playback;
//AudioStream* record;
AudioStream* playback;
AudioStream* record;
//AudioStream* cache;
pa_stream* playback;
pa_stream* record;
//pa_stream* playback;
//pa_stream* record;
};
#endif // _PULSE_LAYER_H_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment