Skip to content
Snippets Groups Projects
Commit 1adb48c2 authored by Alexandre Savard's avatar Alexandre Savard
Browse files

[#5342] Update audio stream initialization

parent 819f7661
No related branches found
No related tags found
No related merge requests found
......@@ -33,17 +33,15 @@
static pa_channel_map channel_map;
AudioStream::AudioStream (PulseLayerType * driver, int smplrate)
AudioStream::AudioStream (pa_context *c, pa_threaded_mainloop *m, std::string desc, int type, int smplrate)
: _audiostream (NULL),
_context (driver->context),
_streamType (driver->type),
_streamDescription (driver->description),
_context (c),
_streamType (type),
_streamDescription (desc),
_volume(),
_flag (PA_STREAM_AUTO_TIMING_UPDATE),
_sample_spec(),
_mainloop (driver->mainloop)
_mainloop (m)
{
_sample_spec.format = PA_SAMPLE_S16LE; // PA_SAMPLE_FLOAT32LE;
_sample_spec.rate = smplrate;
......
......@@ -44,168 +44,178 @@
* This data structure contains the different king of audio streams available
*/
enum STREAM_TYPE {
PLAYBACK_STREAM,
CAPTURE_STREAM,
RINGTONE_STREAM,
UPLOAD_STREAM
PLAYBACK_STREAM, CAPTURE_STREAM, RINGTONE_STREAM, UPLOAD_STREAM
};
struct PulseLayerType {
pa_context * context;
pa_threaded_mainloop * mainloop;
std::string description;
int type;
double volume;
struct AudioStreamParams {
pa_context * context;
pa_threaded_mainloop * mainloop;
std::string description;
int type;
int smplrate;
};
class AudioStream
{
public:
/**
* Constructor
* @param context The PulseLayerType structure containing various information.
*/
AudioStream (PulseLayerType * driver, int smplrate);
/**
* Destructor
*/
~AudioStream();
/**
* Write data to the main abstraction ring buffer.
* @param buffer The buffer containing the data to be played
* @param toCopy The number of samples, in bytes
* @return int The number of bytes played
*/
int putMain (void* buffer , int toCopy);
/**
* Write data to the urgent abstraction ring buffer. ( dtmf , double calls )
* @param buffer The buffer containing the data to be played
* @param toCopy The number of samples, in bytes
* @return int The number of bytes played
*/
int putUrgent (void* buffer , int toCopy);
/**
* Connect the pulse audio stream
*/
bool connectStream (std::string* deviceName);
/**
* Drain the given stream.
*/
bool drainStream (void);
/**
* Disconnect the pulseaudio stream
*/
bool disconnectStream();
/**
* Accessor: Get the pulseaudio stream object
* @return pa_stream* The stream
*/
pa_stream* pulseStream() {
return _audiostream;
}
/**
* Accessor
* @return std::string The stream name
*/
std::string getStreamName (void) {
return _streamDescription;
}
/**
* Accessor
* @param name The stream name
*/
void setStreamName (std::string name) {
_streamDescription = name;
}
void setVolume (double pc) {
_volume.values[0] *= pc/100;
}
pa_cvolume getVolume (void) {
return _volume;
}
/**
* Accessor
* @return stream state
*/
pa_stream_state_t getStreamState (void);
private:
// Copy Constructor
AudioStream (const AudioStream& rh);
// Assignment Operator
AudioStream& operator= (const AudioStream& rh);
/**
* Create the audio stream into the given context
* @param c The pulseaudio context
* @return pa_stream* The newly created audio stream
*/
pa_stream* createStream (pa_context* c, std::string* deviceName);
/**
* Mandatory asynchronous callback on the audio stream state
*/
static void stream_state_callback (pa_stream* s, void* user_data);
/**
* Asynchronous callback on data processing ( write and read )
*/
static void audioCallback (pa_stream* s, size_t bytes, void* userdata);
/**
* Write data to the sound device
*/
void write (void);
/**
* The pulse audio object
*/
pa_stream* _audiostream;
/**
* The pulse audio context
*/
pa_context* _context;
/**
* The type of the stream
*/
int _streamType;
/**
* The name of the stream
*/
std::string _streamDescription;
/**
* Streams parameters
*/
pa_cvolume _volume;
pa_stream_flags_t _flag;
pa_sample_spec _sample_spec ;
pa_threaded_mainloop * _mainloop;
ost::Mutex _mutex;
bool _stream_is_ready;
class AudioStream {
public:
/**
* Constructor
*
* @param context pulseaudio's application context.
* @param mainloop pulseaudio's main loop
* @param description
* @param types
* @param audio sampling rate
*/
AudioStream(pa_context *, pa_threaded_mainloop *, std::string, int, int);
/**
* Destructor
*/
~AudioStream();
/**
* Write data to the main abstraction ring buffer.
* @param buffer The buffer containing the data to be played
* @param toCopy The number of samples, in bytes
* @return int The number of bytes played
*/
int putMain(void* buffer, int toCopy);
/**
* Write data to the urgent abstraction ring buffer. ( dtmf , double calls )
* @param buffer The buffer containing the data to be played
* @param toCopy The number of samples, in bytes
* @return int The number of bytes played
*/
int putUrgent(void* buffer, int toCopy);
/**
* Connect the pulse audio stream
*/
bool connectStream(std::string* deviceName);
/**
* Drain the given stream.
*/
bool drainStream(void);
/**
* Disconnect the pulseaudio stream
*/
bool disconnectStream();
/**
* Accessor: Get the pulseaudio stream object
* @return pa_stream* The stream
*/
pa_stream* pulseStream() {
return _audiostream;
}
/**
* Accessor
* @return std::string The stream name
*/
std::string getStreamName(void) {
return _streamDescription;
}
/**
* Accessor
* @param name The stream name
*/
void setStreamName(std::string name) {
_streamDescription = name;
}
void setVolume(double pc) {
_volume.values[0] *= pc / 100;
}
pa_cvolume getVolume(void) {
return _volume;
}
/**
* Accessor
* @return stream state
*/
pa_stream_state_t getStreamState(void);
private:
// Copy Constructor
AudioStream(const AudioStream& rh);
// Assignment Operator
AudioStream& operator=(const AudioStream& rh);
/**
* Create the audio stream into the given context
* @param c The pulseaudio context
* @return pa_stream* The newly created audio stream
*/
pa_stream* createStream(pa_context* c, std::string* deviceName);
/**
* Mandatory asynchronous callback on the audio stream state
*/
static void stream_state_callback(pa_stream* s, void* user_data);
/**
* Asynchronous callback on data processing ( write and read )
*/
static void audioCallback(pa_stream* s, size_t bytes, void* userdata);
/**
* Write data to the sound device
*/
void write(void);
/**
* The pulse audio object
*/
pa_stream* _audiostream;
/**
* The pulse audio context
*/
pa_context* _context;
/**
* The type of the stream
*/
int _streamType;
/**
* The name of the stream
*/
std::string _streamDescription;
/**
* Streams parameters
*/
pa_cvolume _volume;
/**
* Some special flags for stream connections.
* ex: PA_STREAM_ADJUST_LATENCY, PA_STREAM_START_MUTED, PA_STREAM_VARIABLE_RATE
*/
pa_stream_flags_t _flag;
/**
* A sample format and attribute specification
*/
pa_sample_spec _sample_spec;
/**
* A pointer to the opaque threaded main loop object
*/
pa_threaded_mainloop * _mainloop;
ost::Mutex _mutex;
bool _stream_is_ready;
};
......
......@@ -496,18 +496,11 @@ bool PulseLayer::createStreams (pa_context* c)
std::string recordDevice = _manager->audioPreference.getDeviceRecord();
std::string ringtoneDevice = _manager->audioPreference.getDeviceRingtone();
_debug ("Audio: Device stored in config for playback: %s", playbackDevice.c_str());
_debug ("Audio: Device stored in config for record: %s", recordDevice.c_str());
_debug ("Audio: Device stored in config for ringtone: %s", ringtoneDevice.c_str());
_debug ("Audio: Device for playback: %s", playbackDevice.c_str());
_debug ("Audio: Device for record: %s", recordDevice.c_str());
_debug ("Audio: Device for ringtone: %s", ringtoneDevice.c_str());
PulseLayerType * playbackParam = new PulseLayerType();
playbackParam->context = c;
playbackParam->type = PLAYBACK_STREAM;
playbackParam->description = PLAYBACK_STREAM_NAME;
playbackParam->volume = _manager->getSpkrVolume();
playbackParam->mainloop = m;
playback = new AudioStream (playbackParam, _audioSampleRate);
playback = new AudioStream (c, m, PLAYBACK_STREAM_NAME, PLAYBACK_STREAM, _audioSampleRate);
if (inSinkList (playbackDevice)) {
playback->connectStream (&playbackDevice);
......@@ -521,16 +514,8 @@ bool PulseLayer::createStreams (pa_context* c)
// pa_stream_set_suspended_callback(playback->pulseStream(), stream_suspended_callback, this);
pa_stream_set_moved_callback (playback->pulseStream(), stream_moved_callback, this);
pa_stream_set_latency_update_callback (playback->pulseStream(), latency_update_callback, this);
delete playbackParam;
PulseLayerType * recordParam = new PulseLayerType();
recordParam->context = c;
recordParam->type = CAPTURE_STREAM;
recordParam->description = CAPTURE_STREAM_NAME;
recordParam->volume = _manager->getMicVolume();
recordParam->mainloop = m;
record = new AudioStream (recordParam, _audioSampleRate);
record = new AudioStream (c, m, CAPTURE_STREAM_NAME, CAPTURE_STREAM, _audioSampleRate);
if (inSourceList (recordDevice)) {
record->connectStream (&recordDevice);
......@@ -542,16 +527,8 @@ bool PulseLayer::createStreams (pa_context* c)
// pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this);
pa_stream_set_moved_callback (record->pulseStream(), stream_moved_callback, this);
pa_stream_set_latency_update_callback (record->pulseStream(), latency_update_callback, this);
delete recordParam;
PulseLayerType * ringtoneParam = new PulseLayerType();
ringtoneParam->context = c;
ringtoneParam->type = RINGTONE_STREAM;
ringtoneParam->description = RINGTONE_STREAM_NAME;
ringtoneParam->volume = _manager->getSpkrVolume();
ringtoneParam->mainloop = m;
ringtone = new AudioStream (ringtoneParam, _audioSampleRate);
ringtone = new AudioStream (c, m, RINGTONE_STREAM_NAME, RINGTONE_STREAM, _audioSampleRate*2);
if (inSourceList (ringtoneDevice)) {
ringtone->connectStream (&ringtoneDevice);
......@@ -561,7 +538,6 @@ bool PulseLayer::createStreams (pa_context* c)
pa_stream_set_write_callback (ringtone->pulseStream(), ringtone_callback, this);
pa_stream_set_moved_callback (ringtone->pulseStream(), stream_moved_callback, this);
delete ringtoneParam;
pa_threaded_mainloop_signal (m , 0);
......@@ -716,7 +692,7 @@ void PulseLayer::processCaptureData (void)
void PulseLayer::processRingtoneData (void)
{
// handle ringtone playback
if (ringtone && (ringtone)->pulseStream() && (pa_stream_get_state (ringtone->pulseStream()) == PA_STREAM_READY)) {
if (ringtone && ringtone->pulseStream() && (pa_stream_get_state (ringtone->pulseStream()) == PA_STREAM_READY)) {
// If the playback buffer is full, we don't overflow it; wait for it to have free space
if (pa_stream_writable_size (ringtone->pulseStream()) == 0)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment