diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.cpp b/sflphone-common/src/audio/pulseaudio/audiostream.cpp index 7014905d48f9cb7170ce9d443ec5bf8e89c93049..dbf024d996719a4b6cb97270ef889057c0829872 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.cpp +++ b/sflphone-common/src/audio/pulseaudio/audiostream.cpp @@ -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; diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.h b/sflphone-common/src/audio/pulseaudio/audiostream.h index fcc1d96322204ad9135a354e1734ad0997d182e7..c02ad1826d4001e0d4be4af3184cfb2c192ac28d 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.h +++ b/sflphone-common/src/audio/pulseaudio/audiostream.h @@ -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; }; diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index 6aa3b226e1fe241a05b651fde075ce2e57b92c39..6e0640380a5fcee63f602792891d7d4c5e681bd3 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -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)