From 84ec8623f7e1fab58c7dcc5da5aca3368510b06b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?= Date: Wed, 31 Aug 2011 15:24:53 -0400 Subject: [PATCH] * #6629 simplify alsalayer xrun split audio mainloop into smaller specific functions simplify pulse audiostream remove unused pulse functions --- daemon/src/audio/alsa/alsalayer.cpp | 370 ++++++++++---------- daemon/src/audio/alsa/alsalayer.h | 19 +- daemon/src/audio/pulseaudio/audiostream.cpp | 265 ++++---------- daemon/src/audio/pulseaudio/audiostream.h | 127 +------ daemon/src/audio/pulseaudio/pulselayer.cpp | 253 +++---------- daemon/src/audio/pulseaudio/pulselayer.h | 24 -- daemon/src/managerimpl.cpp | 14 - 7 files changed, 285 insertions(+), 787 deletions(-) diff --git a/daemon/src/audio/alsa/alsalayer.cpp b/daemon/src/audio/alsa/alsalayer.cpp index 01671f0a7..a9ffb4ea1 100644 --- a/daemon/src/audio/alsa/alsalayer.cpp +++ b/daemon/src/audio/alsa/alsalayer.cpp @@ -89,7 +89,6 @@ AlsaLayer::AlsaLayer () , is_capture_running_ (false) , is_playback_open_ (false) , is_capture_open_ (false) - , trigger_request_ (false) , audioThread_ (NULL) { } @@ -427,40 +426,44 @@ bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle) } //TODO first frame causes broken pipe (underrun) because not enough data are send --> make the handle wait to be ready -int +void AlsaLayer::write (void* buffer, int length, snd_pcm_t * handle) { - if (trigger_request_) { - trigger_request_ = false; - startPlaybackStream (); - } - snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames (handle, length); - int err; - if ((err = snd_pcm_writei (handle, buffer , frames)) < 0) { - switch (err) { + int err = snd_pcm_writei (handle, buffer , frames); + if (err >= 0) + return; - case -EPIPE: - case -ESTRPIPE: - case -EIO: - handle_xrun_playback (handle); + switch (err) { - if (snd_pcm_writei (handle, buffer , frames) < 0) - _debug ("Audio: XRUN handling failed"); + case -EPIPE: + case -ESTRPIPE: + case -EIO: + { + snd_pcm_status_t* status; + snd_pcm_status_alloca (&status); - trigger_request_ = true; + err = snd_pcm_status (handle, status); + if (err < 0) + _error("ALSA: Cannot get playback handle status (%s)" , snd_strerror (err)); + else if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN) { + stopPlaybackStream(); + preparePlaybackStream(); + startPlaybackStream(); + } - break; + err = snd_pcm_writei (handle, buffer , frames); + if (err < 0) + _error("ALSA: XRUN handling failed : %s", snd_strerror(err)); + break; + } - default: - _debug ("Audio: Write error unknown - dropping frames: %s", snd_strerror (err)); - stopPlaybackStream (); - break; - } - } - - return (err > 0) ? err : 0 ; + default: + _error("ALSA: unknown write error, dropping frames: %s", snd_strerror (err)); + stopPlaybackStream (); + break; + } } int @@ -473,68 +476,43 @@ AlsaLayer::read (void* buffer, int toCopy) snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames (captureHandle_, toCopy); - int err; - if ((err = snd_pcm_readi (captureHandle_, buffer, frames)) < 0) { - switch (err) { + int err = snd_pcm_readi (captureHandle_, buffer, frames); + if (err >= 0) + return snd_pcm_frames_to_bytes(captureHandle_, frames); - case -EPIPE: - case -ESTRPIPE: - case -EIO: - _debug ("Audio: XRUN capture ignored (%s)", snd_strerror (err)); - handle_xrun_capture(); - break; + switch (err) { - case EPERM: - _debug ("Audio: Capture EPERM (%s)", snd_strerror (err)); - prepareCaptureStream (); - startCaptureStream (); - break; + case -EPIPE: + case -ESTRPIPE: + case -EIO: + { + snd_pcm_status_t* status; + snd_pcm_status_alloca (&status); - default: - break; - } + err = snd_pcm_status(captureHandle_, status); + if (err < 0) + _error("ALSA: Get status failed: %s", snd_strerror(err)); + else if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN) { + stopCaptureStream (); + prepareCaptureStream (); + startCaptureStream (); + } - return 0; - } + _error("ALSA: XRUN capture ignored (%s)", snd_strerror (err)); + break; + } - return toCopy; -} + case EPERM: + _error("ALSA: Can't capture, EPERM (%s)", snd_strerror (err)); + prepareCaptureStream (); + startCaptureStream (); + break; -void -AlsaLayer::handle_xrun_capture (void) -{ - snd_pcm_status_t* status; - snd_pcm_status_alloca (&status); + default: + break; + } - if (snd_pcm_status(captureHandle_, status) <= 0) { - if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN) { - stopCaptureStream (); - prepareCaptureStream (); - startCaptureStream (); - } - } else - _debug ("Audio: Get status failed"); -} - -void -AlsaLayer::handle_xrun_playback (snd_pcm_t *handle) -{ - snd_pcm_status_t* status; - snd_pcm_status_alloca (&status); - - int state; - if ((state = snd_pcm_status (handle, status)) < 0) - _debug ("Audio: Error: Cannot get playback handle status (%s)" , snd_strerror (state)); - else { - int state = snd_pcm_status_get_state (status); - - if (state == SND_PCM_STATE_XRUN) { - stopPlaybackStream (); - preparePlaybackStream (); - - trigger_request_ = true; - } - } + return 0; } std::string @@ -645,33 +623,122 @@ namespace } } -void AlsaLayer::audioCallback (void) +void AlsaLayer::capture(void) { unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); bool resample = audioSampleRate_ != mainBufferSampleRate; + int toGetSamples = snd_pcm_avail_update (captureHandle_); + if (toGetSamples < 0) + _error ("Audio: Mic error: %s", snd_strerror (toGetSamples)); + if (toGetSamples <= 0) + return; + + const int framesPerBufferAlsa = 2048; + if (toGetSamples > framesPerBufferAlsa) + toGetSamples = framesPerBufferAlsa; + + int toGetBytes = toGetSamples * sizeof(SFLDataFormat); + SFLDataFormat* in = (SFLDataFormat*) malloc (toGetBytes); + if (read(in, toGetBytes) != toGetBytes) { + _error("ALSA MIC : Couldn't read!"); + goto end; + } + adjustVolume (in, toGetSamples, Manager::instance().getSpkrVolume()); + + if (resample) { + int outSamples = toGetSamples * ((double) audioSampleRate_ / mainBufferSampleRate); + int outBytes = outSamples * sizeof (SFLDataFormat); + SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (outBytes); + converter_->resample ( (SFLDataFormat*) in, rsmpl_out, mainBufferSampleRate, audioSampleRate_, toGetSamples); + dcblocker_.process(rsmpl_out, outBytes); + getMainBuffer()->putData (rsmpl_out, outBytes); + free (rsmpl_out); + } else { + SFLDataFormat* filter_out = (SFLDataFormat*) malloc (toGetBytes); + dcblocker_.process(in, filter_out, toGetBytes); + getMainBuffer()->putData (filter_out, toGetBytes); + free (filter_out); + } + +end: + free (in); +} + +void AlsaLayer::playback(int maxSamples) +{ + unsigned short spkrVolume = Manager::instance().getSpkrVolume(); + + unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); + bool resample = audioSampleRate_ != mainBufferSampleRate; + + int toGet = getMainBuffer()->availForGet(); + int toPut = maxSamples * sizeof(SFLDataFormat); + + if (toGet <= 0) { // no audio available, play tone or silence + AudioLoop *tone = Manager::instance().getTelephoneTone(); + AudioLoop *file_tone = Manager::instance().getTelephoneFile(); + + SFLDataFormat *out = (SFLDataFormat *) malloc (toPut); + + if (tone) + tone->getNext (out, maxSamples, spkrVolume); + else if (file_tone && !ringtoneHandle_) + file_tone->getNext (out, maxSamples, spkrVolume); + else + memset(out, 0, toPut); + + write (out, toPut, playbackHandle_); + free (out); + return; + } + // play the regular sound samples + + int maxNbBytesToGet = toPut; + // Compute maximal value to get from the ring buffer + double resampleFactor = 1.0; + if (resample) { + resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; + maxNbBytesToGet = (double) toGet / resampleFactor; + } + + if (toGet > maxNbBytesToGet) + toGet = maxNbBytesToGet; + + SFLDataFormat *out = (SFLDataFormat*) malloc (toGet); + getMainBuffer()->getData (out, toGet); + adjustVolume(out, toGet / sizeof(SFLDataFormat), spkrVolume); + + if (resample) { + int inSamples = toGet / sizeof(SFLDataFormat); + int outSamples = inSamples * resampleFactor; + SFLDataFormat *rsmpl_out = (SFLDataFormat*) malloc (outSamples * sizeof(SFLDataFormat)); + converter_->resample (out, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples); + write (rsmpl_out, outSamples * sizeof(SFLDataFormat), playbackHandle_); + free (rsmpl_out); + } else { + write (out, toGet, playbackHandle_); + } + free (out); +} + +void AlsaLayer::audioCallback (void) +{ + if (!playbackHandle_ or !captureHandle_) + return; + notifyincomingCall(); unsigned short spkrVolume = Manager::instance().getSpkrVolume(); - AudioLoop *tone = Manager::instance().getTelephoneTone(); - AudioLoop *file_tone = Manager::instance().getTelephoneFile(); - - // AvailForGet tell the number of chars inside the buffer - // framePerBuffer are the number of data for one channel (left) - int urgentAvailBytes = urgentRingBuffer_.AvailForGet(); - - if (!playbackHandle_ or !captureHandle_) - return; - snd_pcm_wait (playbackHandle_, 20); int playbackAvailSmpl = snd_pcm_avail_update (playbackHandle_); int playbackAvailBytes = playbackAvailSmpl * sizeof (SFLDataFormat); - if (urgentAvailBytes > 0) { + int toGet = urgentRingBuffer_.AvailForGet(); + if (toGet > 0) { // Urgent data (dtmf, incoming call signal) come first. - int toGet = urgentAvailBytes; if (toGet > playbackAvailBytes) toGet = playbackAvailBytes; SFLDataFormat *out = (SFLDataFormat*) malloc (toGet); @@ -684,109 +751,26 @@ void AlsaLayer::audioCallback (void) getMainBuffer()->discard (toGet); } else { // regular audio data - int toGet = getMainBuffer()->availForGet(); - - if (toGet <= 0) { - // no audio available, play tone or silence - SFLDataFormat *out = (SFLDataFormat *) malloc (playbackAvailBytes); - - if (tone) - tone->getNext (out, playbackAvailSmpl, spkrVolume); - else if (file_tone && !ringtoneHandle_) - file_tone->getNext (out, playbackAvailSmpl, spkrVolume); - else - memset(out, 0, playbackAvailBytes); - - write (out, playbackAvailBytes, playbackHandle_); - free (out); - } else { - // play the regular sound samples - - int maxNbBytesToGet = playbackAvailBytes; - // Compute maximal value to get from the ring buffer - double resampleFactor = 1.0; - if (resample) { - resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; - maxNbBytesToGet = (double) toGet / resampleFactor; - } - - if (toGet > maxNbBytesToGet) - toGet = maxNbBytesToGet; - - SFLDataFormat *out = (SFLDataFormat*) malloc (toGet); - getMainBuffer()->getData (out, toGet); - adjustVolume(out, toGet / sizeof(SFLDataFormat), spkrVolume); - - if (resample) { - int inSamples = toGet / sizeof(SFLDataFormat); - int outSamples = inSamples * resampleFactor; - SFLDataFormat *rsmpl_out = (SFLDataFormat*) malloc (outSamples * sizeof(SFLDataFormat)); - converter_->resample (out, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples); - write (rsmpl_out, outSamples * sizeof(SFLDataFormat), playbackHandle_); - free (rsmpl_out); - } else { - write (out, toGet, playbackHandle_); - } - free (out); - } + playback(playbackAvailSmpl); } - if (file_tone and ringtoneHandle_) { - int ringtoneAvailSmpl = snd_pcm_avail_update (ringtoneHandle_); - int ringtoneAvailBytes = ringtoneAvailSmpl*sizeof (SFLDataFormat); - SFLDataFormat *out = (SFLDataFormat *) malloc (ringtoneAvailBytes); - file_tone->getNext (out, ringtoneAvailSmpl, spkrVolume); - write (out, ringtoneAvailBytes, ringtoneHandle_); - free (out); - } else if (ringtoneHandle_) { - int ringtoneAvailSmpl = snd_pcm_avail_update (ringtoneHandle_); - int ringtoneAvailBytes = ringtoneAvailSmpl*sizeof (SFLDataFormat); + if (ringtoneHandle_) { + AudioLoop *file_tone = Manager::instance().getTelephoneFile(); + int ringtoneAvailSmpl = snd_pcm_avail_update (ringtoneHandle_); + int ringtoneAvailBytes = ringtoneAvailSmpl*sizeof (SFLDataFormat); - SFLDataFormat *out = (SFLDataFormat *) malloc (ringtoneAvailBytes); - memset (out, 0, ringtoneAvailBytes); - write (out, ringtoneAvailBytes, ringtoneHandle_); - free (out); + SFLDataFormat *out = (SFLDataFormat *) malloc (ringtoneAvailBytes); + + if (file_tone) + file_tone->getNext (out, ringtoneAvailSmpl, spkrVolume); + else + memset (out, 0, ringtoneAvailBytes); + + write(out, ringtoneAvailBytes, ringtoneHandle_); + free(out); } // Additionally handle the mic's audio stream - if (!is_capture_running_) - return; - - int toPutSamples = snd_pcm_avail_update (captureHandle_); - if (toPutSamples <= 0) { - if (toPutSamples < 0) - _error ("Audio: Mic error: %s", snd_strerror (toPutSamples)); - return; - } - - const int framesPerBufferAlsa = 2048; - if (toPutSamples > framesPerBufferAlsa) - toPutSamples = framesPerBufferAlsa; - - int toPutBytes = toPutSamples * sizeof(SFLDataFormat); - SFLDataFormat* in = (SFLDataFormat*) malloc (toPutBytes); - int bytes = read (in, toPutBytes); - if (toPutBytes != bytes) { - _error("ALSA MIC : Couldn't read!"); - free(in); - return; - } - adjustVolume (in, toPutSamples, spkrVolume); - - if (resample) { - int outSamples = toPutSamples * ((double) audioSampleRate_ / mainBufferSampleRate); - int outBytes = outSamples * sizeof (SFLDataFormat); - SFLDataFormat* rsmpl_out = (SFLDataFormat*) malloc (outBytes); - converter_->resample ( (SFLDataFormat*) in, rsmpl_out, mainBufferSampleRate, audioSampleRate_, toPutSamples); - dcblocker_.process(rsmpl_out, outBytes); - getMainBuffer()->putData (rsmpl_out, outBytes); - free (rsmpl_out); - } else { - SFLDataFormat* filter_out = (SFLDataFormat*) malloc (toPutBytes); - dcblocker_.process(in, filter_out, toPutBytes); - getMainBuffer()->putData (filter_out, toPutBytes); - free (filter_out); - } - - free (in); + if (is_capture_running_) + capture(); } diff --git a/daemon/src/audio/alsa/alsalayer.h b/daemon/src/audio/alsa/alsalayer.h index a8a8629c8..d81997e6f 100644 --- a/daemon/src/audio/alsa/alsalayer.h +++ b/daemon/src/audio/alsa/alsalayer.h @@ -124,6 +124,9 @@ class AlsaLayer : public AudioLayer return audioPlugin_; } + void playback(int maxSamples); + void capture(void); + void audioCallback (void); /** @@ -204,9 +207,8 @@ class AlsaLayer : public AudioLayer * ALSA Library API * @param buffer The data to be copied * @param length The size of the buffer - * @return int The number of frames actually copied */ - int write (void* buffer, int length, snd_pcm_t *handle); + void write (void* buffer, int length, snd_pcm_t *handle); /** * Read data from the internal ring buffer @@ -217,18 +219,6 @@ class AlsaLayer : public AudioLayer */ int read (void* buffer, int toCopy); - /** - * Recover from XRUN state for capture - * ALSA Library API - */ - void handle_xrun_capture (void); - - /** - * Recover from XRUN state for playback - * ALSA Library API - */ - void handle_xrun_playback (snd_pcm_t *handle); - /** * Handles to manipulate playback stream * ALSA Library API @@ -266,7 +256,6 @@ class AlsaLayer : public AudioLayer bool is_capture_running_; bool is_playback_open_; bool is_capture_open_; - bool trigger_request_; AlsaThread* audioThread_; }; diff --git a/daemon/src/audio/pulseaudio/audiostream.cpp b/daemon/src/audio/pulseaudio/audiostream.cpp index b09eb6d10..3a5ae0563 100644 --- a/daemon/src/audio/pulseaudio/audiostream.cpp +++ b/daemon/src/audio/pulseaudio/audiostream.cpp @@ -31,247 +31,104 @@ #include #include "pulselayer.h" -static pa_channel_map channel_map; - -AudioStream::AudioStream (pa_context *c, pa_threaded_mainloop *m, std::string desc, int type, int smplrate) - : _audiostream (NULL), - _context (c), - _streamType (type), - _streamDescription (desc), - _volume(), - _flag (PA_STREAM_AUTO_TIMING_UPDATE), - _sample_spec(), - _mainloop (m) +AudioStream::AudioStream (pa_context *c, pa_threaded_mainloop *m, const char *desc, int type, int smplrate, std::string *deviceName) + : _mainloop (m) { - _sample_spec.format = PA_SAMPLE_S16LE; // PA_SAMPLE_FLOAT32LE; - _sample_spec.rate = smplrate; - _sample_spec.channels = 1; - channel_map.channels = 1; - pa_cvolume_set (&_volume , 1 , PA_VOLUME_NORM) ; // * vol / 100 ; + static const pa_channel_map channel_map = { + 1, + { PA_CHANNEL_POSITION_MONO }, + }; + + pa_sample_spec sample_spec = { + PA_SAMPLE_S16LE, // PA_SAMPLE_FLOAT32LE, + smplrate, + 1 + }; + + assert (pa_sample_spec_valid (&sample_spec)); + assert (pa_channel_map_valid (&channel_map)); + + _audiostream = pa_stream_new (c, desc, &sample_spec, &channel_map); + if (!_audiostream) { + _error("Pulse: %s: pa_stream_new() failed : %s" , desc, pa_strerror (pa_context_errno (c))); + throw std::runtime_error("Pulse : could not create stream\n"); + } + + pa_buffer_attr attributes; + attributes.maxlength = pa_usec_to_bytes (160 * PA_USEC_PER_MSEC, &sample_spec); + attributes.tlength = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &sample_spec); + attributes.prebuf = 0; + attributes.fragsize = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &sample_spec); + attributes.minreq = (uint32_t) -1; + + const char *name = deviceName ? deviceName->c_str() : NULL; + + pa_threaded_mainloop_lock (_mainloop); + + if (type == PLAYBACK_STREAM || type == RINGTONE_STREAM) + pa_stream_connect_playback (_audiostream , name, &attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); + else if (type == CAPTURE_STREAM) + pa_stream_connect_record (_audiostream, name, &attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE)); + + pa_threaded_mainloop_unlock (_mainloop); + + pa_stream_set_state_callback (_audiostream , stream_state_callback, NULL); } AudioStream::~AudioStream() { - disconnectStream(); -} - -bool -AudioStream::connectStream (std::string* deviceName) -{ - ost::MutexLock guard (_mutex); - - if (!_audiostream) - _audiostream = createStream (_context, deviceName); - - return true; -} - -static void success_cb (pa_stream *s, int success UNUSED, void *userdata) -{ - - assert (s); - - pa_threaded_mainloop * mainloop = (pa_threaded_mainloop *) userdata; - - pa_threaded_mainloop_signal (mainloop, 0); -} - -bool -AudioStream::drainStream (void) -{ - if (_audiostream) { - _info ("Audio: Draining stream"); - pa_operation * operation; - - pa_threaded_mainloop_lock (_mainloop); - - if ( (operation = pa_stream_drain (_audiostream, success_cb, _mainloop))) { - while (pa_operation_get_state (operation) != PA_OPERATION_DONE) { - if (!_context || pa_context_get_state (_context) != PA_CONTEXT_READY || !_audiostream || pa_stream_get_state (_audiostream) != PA_STREAM_READY) { - _warn ("Audio: Connection died: %s", _context ? pa_strerror (pa_context_errno (_context)) : "NULL"); - pa_operation_unref (operation); - break; - } else { - pa_threaded_mainloop_wait (_mainloop); - } - } - } - - pa_threaded_mainloop_unlock (_mainloop); - } - - return true; -} - -bool -AudioStream::disconnectStream (void) -{ - _info ("Audio: Destroy audio streams"); - pa_threaded_mainloop_lock (_mainloop); - if (_audiostream) { - pa_stream_disconnect (_audiostream); + pa_stream_disconnect (_audiostream); - // make sure we don't get any further callback - pa_stream_set_state_callback (_audiostream, NULL, NULL); - pa_stream_set_write_callback (_audiostream, NULL, NULL); - pa_stream_set_underflow_callback (_audiostream, NULL, NULL); - pa_stream_set_overflow_callback (_audiostream, NULL, NULL); + // make sure we don't get any further callback + pa_stream_set_state_callback (_audiostream, NULL, NULL); + pa_stream_set_write_callback (_audiostream, NULL, NULL); + pa_stream_set_underflow_callback (_audiostream, NULL, NULL); + pa_stream_set_overflow_callback (_audiostream, NULL, NULL); - pa_stream_unref (_audiostream); - _audiostream = NULL; - } + pa_stream_unref (_audiostream); pa_threaded_mainloop_unlock (_mainloop); - - return true; } - - void AudioStream::stream_state_callback (pa_stream* s, void* user_data) { - pa_threaded_mainloop *m; - - _info ("Audio: The state of the stream changed"); - assert (s); - char str[PA_SAMPLE_SPEC_SNPRINT_MAX]; - m = (pa_threaded_mainloop*) user_data; - assert (m); - switch (pa_stream_get_state (s)) { case PA_STREAM_CREATING: - _info ("Audio: Stream is creating..."); + _info ("Pulse: Stream is creating..."); break; case PA_STREAM_TERMINATED: - _info ("Audio: Stream is terminating..."); + _info ("Pulse: Stream is terminating..."); break; case PA_STREAM_READY: - _info ("Audio: Stream successfully created, connected to %s", pa_stream_get_device_name (s)); - // pa_buffer_attr *buffattr = (pa_buffer_attr *)pa_xmalloc (sizeof(pa_buffer_attr)); - _debug ("Audio: maxlength %u", pa_stream_get_buffer_attr (s)->maxlength); - _debug ("Audio: tlength %u", pa_stream_get_buffer_attr (s)->tlength); - _debug ("Audio: prebuf %u", pa_stream_get_buffer_attr (s)->prebuf); - _debug ("Audio: minreq %u", pa_stream_get_buffer_attr (s)->minreq); - _debug ("Audio: fragsize %u", pa_stream_get_buffer_attr (s)->fragsize); - _debug ("Audio: samplespec %s", pa_sample_spec_snprint (str, sizeof (str), pa_stream_get_sample_spec (s))); - // pa_xfree (buffattr); + _info ("Pulse: Stream successfully created, connected to %s", pa_stream_get_device_name (s)); + _debug ("Pulse: maxlength %u", pa_stream_get_buffer_attr (s)->maxlength); + _debug ("Pulse: tlength %u", pa_stream_get_buffer_attr (s)->tlength); + _debug ("Pulse: prebuf %u", pa_stream_get_buffer_attr (s)->prebuf); + _debug ("Pulse: minreq %u", pa_stream_get_buffer_attr (s)->minreq); + _debug ("Pulse: fragsize %u", pa_stream_get_buffer_attr (s)->fragsize); + _debug ("Pulse: samplespec %s", pa_sample_spec_snprint (str, sizeof (str), pa_stream_get_sample_spec (s))); break; case PA_STREAM_UNCONNECTED: - _info ("Audio: Stream unconnected"); + _info ("Pulse: Stream unconnected"); break; case PA_STREAM_FAILED: - default: - _warn ("Audio: Error - Sink/Source doesn't exists: %s" , pa_strerror (pa_context_errno (pa_stream_get_context (s)))); - exit (0); + _error("Pulse: Sink/Source doesn't exists: %s" , pa_strerror (pa_context_errno (pa_stream_get_context (s)))); break; } } -pa_stream_state_t -AudioStream::getStreamState (void) +bool AudioStream::isReady (void) { - - ost::MutexLock guard (_mutex); - return pa_stream_get_state (_audiostream); + return pa_stream_get_state (_audiostream) == PA_STREAM_READY; } - - - -pa_stream* -AudioStream::createStream (pa_context* c, std::string *deviceName) -{ - ost::MutexLock guard (_mutex); - - pa_stream* s; - - assert (pa_sample_spec_valid (&_sample_spec)); - assert (pa_channel_map_valid (&channel_map)); - - _info ("Audio: Create pulseaudio stream: %d", _sample_spec.rate); - - pa_buffer_attr* attributes = new pa_buffer_attr; - - - if (! (s = pa_stream_new (c, _streamDescription.c_str() , &_sample_spec, &channel_map))) - _warn ("Audio: Error: %s: pa_stream_new() failed : %s" , _streamDescription.c_str(), pa_strerror (pa_context_errno (c))); - - assert (s); - - if (_streamType == PLAYBACK_STREAM) { - - attributes->maxlength = pa_usec_to_bytes (160 * PA_USEC_PER_MSEC, &_sample_spec); // -1; - attributes->tlength = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &_sample_spec); - attributes->prebuf = 0; - attributes->fragsize = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &_sample_spec); - attributes->minreq = (uint32_t) -1; - - pa_threaded_mainloop_lock (_mainloop); - - if (deviceName) - pa_stream_connect_playback (s , deviceName->c_str(), attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); - else - pa_stream_connect_playback (s , NULL, attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); - - - pa_threaded_mainloop_unlock (_mainloop); - - } else if (_streamType == CAPTURE_STREAM) { - - attributes->maxlength = pa_usec_to_bytes (160 * PA_USEC_PER_MSEC, &_sample_spec);// (uint32_t) -1; - attributes->tlength = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &_sample_spec);// pa_usec_to_bytes (20 * PA_USEC_PER_MSEC, &_sample_spec); - attributes->prebuf = 0; - attributes->fragsize = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &_sample_spec); // pa_usec_to_bytes (20 * PA_USEC_PER_MSEC, &_sample_spec); - attributes->minreq = (uint32_t) -1; - - pa_threaded_mainloop_lock (_mainloop); - - if (deviceName) - pa_stream_connect_record (s, deviceName->c_str(), attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE)); - else - pa_stream_connect_record (s, NULL, attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE)); - - - pa_threaded_mainloop_unlock (_mainloop); - - } else if (_streamType == RINGTONE_STREAM) { - - attributes->maxlength = pa_usec_to_bytes (160 * PA_USEC_PER_MSEC, &_sample_spec);; - attributes->tlength = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &_sample_spec); - attributes->prebuf = 0; - attributes->fragsize = pa_usec_to_bytes (80 * PA_USEC_PER_MSEC, &_sample_spec); - attributes->minreq = (uint32_t) -1; - - pa_threaded_mainloop_lock (_mainloop); - - if (deviceName) - pa_stream_connect_playback (s, deviceName->c_str(), attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); - else - pa_stream_connect_playback (s, NULL, attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY), NULL, NULL); - - pa_threaded_mainloop_unlock (_mainloop); - - } else if (_streamType == UPLOAD_STREAM) { - pa_stream_connect_upload (s , 1024); - } else { - _warn ("Audio: Error: Stream type unknown "); - } - - pa_stream_set_state_callback (s , stream_state_callback, _mainloop); - - - delete attributes; - - return s; -} - diff --git a/daemon/src/audio/pulseaudio/audiostream.h b/daemon/src/audio/pulseaudio/audiostream.h index 00d405efa..00eb7a2e1 100644 --- a/daemon/src/audio/pulseaudio/audiostream.h +++ b/daemon/src/audio/pulseaudio/audiostream.h @@ -34,25 +34,11 @@ #include #include -#include "global.h" -#include "audio/ringbuffer.h" -#include "audio/audioloop.h" - -#include - /** * This data structure contains the different king of audio streams available */ enum STREAM_TYPE { - PLAYBACK_STREAM, CAPTURE_STREAM, RINGTONE_STREAM, UPLOAD_STREAM -}; - -struct AudioStreamParams { - pa_context * context; - pa_threaded_mainloop * mainloop; - std::string description; - int type; - int smplrate; + PLAYBACK_STREAM, CAPTURE_STREAM, RINGTONE_STREAM }; class AudioStream { @@ -66,37 +52,12 @@ public: * @param description * @param types * @param audio sampling rate + * @param device name */ - AudioStream(pa_context *, pa_threaded_mainloop *, std::string, int, int); + AudioStream(pa_context *, pa_threaded_mainloop *, const char *, int, int, std::string *); - /** - * Destructor - */ ~AudioStream(); - /** - * 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 @@ -105,34 +66,7 @@ public: 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); + bool isReady(void); private: @@ -142,73 +76,20 @@ private: // 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; - }; #endif // _AUDIO_STREAM_H diff --git a/daemon/src/audio/pulseaudio/pulselayer.cpp b/daemon/src/audio/pulseaudio/pulselayer.cpp index 42d29b390..7ae83174a 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.cpp +++ b/daemon/src/audio/pulseaudio/pulselayer.cpp @@ -54,11 +54,9 @@ void capture_callback (pa_stream* s, size_t bytes, void* userdata) void ringtone_callback (pa_stream* s, size_t bytes, void* userdata) { - assert (s && bytes); assert (bytes > 0); static_cast (userdata)->processRingtoneData(); - } void stream_moved_callback (pa_stream *s, void *userdata UNUSED) @@ -66,23 +64,6 @@ void stream_moved_callback (pa_stream *s, void *userdata UNUSED) _debug ("stream_moved_callback: stream %d to %d", pa_stream_get_index (s), pa_stream_get_device_index (s)); } -void latency_update_callback (pa_stream *p, void *userdata UNUSED) -{ - - pa_usec_t r_usec; - - pa_stream_get_latency (p, &r_usec, NULL); - - /* - _debug ("Audio: Stream letency update %0.0f ms for device %s", (float) r_usec/1000, pa_stream_get_device_name (p)); - _debug ("Audio: maxlength %u", pa_stream_get_buffer_attr (p)->maxlength); - _debug ("Audio: tlength %u", pa_stream_get_buffer_attr (p)->tlength); - _debug ("Audio: prebuf %u", pa_stream_get_buffer_attr (p)->prebuf); - _debug ("Audio: minreq %u", pa_stream_get_buffer_attr (p)->minreq); - _debug ("Audio: fragsize %u", pa_stream_get_buffer_attr (p)->fragsize); - */ -} - void sink_input_info_callback (pa_context *c UNUSED, const pa_sink_info *i, int eol, void *userdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; @@ -208,12 +189,6 @@ void context_changed_callback (pa_context* c, pa_subscription_event_type_t t, ui } } - -void playback_underflow_callback (pa_stream* s UNUSED, void* userdata UNUSED) -{} - -void playback_overflow_callback (pa_stream* s UNUSED, void* userdata UNUSED) -{} } // end anonymous namespace @@ -227,25 +202,25 @@ PulseLayer::PulseLayer () mainloop_ = pa_threaded_mainloop_new(); if (!mainloop_) - _error("Couldn't create pulseaudio mainloop"); + throw std::runtime_error("Couldn't create pulseaudio mainloop"); context_ = pa_context_new (pa_threaded_mainloop_get_api (mainloop_) , "SFLphone"); if (!context_) - _error("Couldn't create pulseaudio context"); + throw std::runtime_error("Couldn't create pulseaudio context"); pa_context_set_state_callback (context_, context_state_callback, this); if (pa_context_connect (context_, NULL , PA_CONTEXT_NOAUTOSPAWN , NULL) < 0) - _error("Could not connect pulseaudio context to the server"); + throw std::runtime_error("Could not connect pulseaudio context to the server"); pa_threaded_mainloop_lock (mainloop_); if (pa_threaded_mainloop_start (mainloop_) < 0) - _error("Failed to start pulseaudio mainloop"); + throw std::runtime_error("Failed to start pulseaudio mainloop"); pa_threaded_mainloop_wait (mainloop_); if (pa_context_get_state (context_) != PA_CONTEXT_READY) - _error("Couldn't connect to pulse audio server"); + throw std::runtime_error("Couldn't connect to pulse audio server"); pa_threaded_mainloop_unlock (mainloop_); @@ -270,7 +245,6 @@ PulseLayer::~PulseLayer (void) void PulseLayer::context_state_callback (pa_context* c, void* user_data) { - _info ("Audio: The state of the context changed"); PulseLayer* pulse = (PulseLayer*) user_data; assert (c && pulse->mainloop_); @@ -294,13 +268,12 @@ void PulseLayer::context_state_callback (pa_context* c, void* user_data) break; case PA_CONTEXT_TERMINATED: - _debug ("Audio: Context terminated"); break; case PA_CONTEXT_FAILED: default: - _warn ("Audio: Error : %s" , pa_strerror (pa_context_errno (c))); + _error("Pulse: %s" , pa_strerror (pa_context_errno (c))); pa_threaded_mainloop_signal (pulse->mainloop_, 0); pulse->disconnectAudioStream(); break; @@ -341,24 +314,20 @@ void PulseLayer::createStreams (pa_context* c) _debug ("PulseAudio: Devices: playback %s , record %s , ringtone %s", playbackDevice.c_str(), recordDevice.c_str(), ringtoneDevice.c_str()); - playback_ = new AudioStream (c, mainloop_, PLAYBACK_STREAM_NAME, PLAYBACK_STREAM, audioSampleRate_); - playback_->connectStream(inSinkList(playbackDevice) ? &playbackDevice : NULL); + playback_ = new AudioStream (c, mainloop_, PLAYBACK_STREAM_NAME, PLAYBACK_STREAM, audioSampleRate_, + inSinkList(playbackDevice) ? &playbackDevice : NULL); pa_stream_set_write_callback (playback_->pulseStream(), playback_callback, this); - pa_stream_set_overflow_callback (playback_->pulseStream(), playback_overflow_callback, this); - pa_stream_set_underflow_callback (playback_->pulseStream(), playback_underflow_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); - record_ = new AudioStream (c, mainloop_, CAPTURE_STREAM_NAME, CAPTURE_STREAM, audioSampleRate_); - record_->connectStream (inSourceList(recordDevice) ? &recordDevice : NULL); + record_ = new AudioStream (c, mainloop_, CAPTURE_STREAM_NAME, CAPTURE_STREAM, audioSampleRate_, + inSourceList(recordDevice) ? &recordDevice : NULL); pa_stream_set_read_callback (record_->pulseStream() , capture_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); - ringtone_ = new AudioStream (c, mainloop_, RINGTONE_STREAM_NAME, RINGTONE_STREAM, audioSampleRate_); - ringtone_->connectStream(inSourceList(ringtoneDevice) ? &ringtoneDevice : NULL); + ringtone_ = new AudioStream (c, mainloop_, RINGTONE_STREAM_NAME, RINGTONE_STREAM, audioSampleRate_, + inSourceList(ringtoneDevice) ? &ringtoneDevice : NULL); pa_stream_set_write_callback (ringtone_->pulseStream(), ringtone_callback, this); pa_stream_set_moved_callback (ringtone_->pulseStream(), stream_moved_callback, this); @@ -423,8 +392,6 @@ void PulseLayer::startStream (void) void PulseLayer::stopStream (void) { - _info ("Audio: Stop audio stream"); - pa_threaded_mainloop_lock (mainloop_); if (playback_) @@ -501,7 +468,7 @@ void PulseLayer::writeToSpeaker (void) // available bytes to be written in pulseaudio internal buffer int writeableSizeBytes = pa_stream_writable_size (playback_->pulseStream()); if (writeableSizeBytes < 0) { - _error ("Audio: playback error : %s", pa_strerror (writeableSizeBytes)); + _error("Pulse: playback error : %s", pa_strerror (writeableSizeBytes)); return; } @@ -520,7 +487,7 @@ void PulseLayer::writeToSpeaker (void) AudioLoop *toneToPlay = Manager::instance().getTelephoneTone(); if (toneToPlay) { - if (playback_->getStreamState() == PA_STREAM_READY) { + if (playback_->isReady()) { SFLDataFormat *out = (SFLDataFormat*) pa_xmalloc (writeableSizeBytes); toneToPlay->getNext (out, writeableSizeBytes / sizeof (SFLDataFormat), 100); pa_stream_write (playback_->pulseStream(), out, writeableSizeBytes, NULL, 0, PA_SEEK_RELATIVE); @@ -577,8 +544,9 @@ void PulseLayer::writeToSpeaker (void) void PulseLayer::readFromMic (void) { - const char* data = NULL; + const char *data = NULL; size_t r; + SFLDataFormat *out; unsigned int mainBufferSampleRate = getMainBuffer()->getInternalSamplingRate(); bool resample = audioSampleRate_ != mainBufferSampleRate; @@ -589,25 +557,22 @@ void PulseLayer::readFromMic (void) } if (resample) { - int inSamples = r / sizeof(SFLDataFormat); double resampleFactor = (double) audioSampleRate_ / mainBufferSampleRate; - int outSamples = (double) inSamples * resampleFactor; - int outBytes = outSamples * sizeof(SFLDataFormat); - - SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (outBytes); - converter_->resample ( (SFLDataFormat *) data, rsmpl_out, mainBufferSampleRate, audioSampleRate_, inSamples); - // remove dc offset - dcblocker_.process(rsmpl_out, outBytes); - getMainBuffer()->putData (rsmpl_out, outBytes); - pa_xfree (rsmpl_out); - } else { - SFLDataFormat* filter_out = (SFLDataFormat*) pa_xmalloc (r); - // remove dc offset - dcblocker_.process( (SFLDataFormat *) data, filter_out, r); - getMainBuffer()->putData (filter_out, r); - pa_xfree (filter_out); + r = (double) r * resampleFactor; } + out = (SFLDataFormat*) pa_xmalloc (r); + + if (resample) { + converter_->resample ( (SFLDataFormat *) data, out, mainBufferSampleRate, audioSampleRate_, r / sizeof(SFLDataFormat)); + dcblocker_.process(out, r); + } else { + dcblocker_.process( (SFLDataFormat *) data, out, r); + } + + getMainBuffer()->putData (out, r); + pa_xfree (out); + end: if (pa_stream_drop (record_->pulseStream()) < 0) _error ("Audio: Error: capture stream drop failed: %s" , pa_strerror (pa_context_errno (context_))); @@ -616,161 +581,21 @@ end: void PulseLayer::ringtoneToSpeaker (void) { - AudioLoop* fileToPlay = Manager::instance().getTelephoneFile(); int writableSize = pa_stream_writable_size (ringtone_->pulseStream()); - if (fileToPlay) { + if (!ringtone_->isReady()) { + _error("PulseAudio: Error: Ringtone stream not in state ready"); + return; + } - if (ringtone_->getStreamState() != PA_STREAM_READY) { - _error("PulseAudio: Error: Ringtone stream not in state ready"); - return; - } - - SFLDataFormat *out = (SFLDataFormat *) pa_xmalloc (writableSize); - if (out == NULL) { - _error("PulseAudio: Error: Could not allocate memory for buffer"); - return; - } - - memset (out, 0, writableSize); + SFLDataFormat *out = (SFLDataFormat *) pa_xmalloc (writableSize); + AudioLoop *fileToPlay = Manager::instance().getTelephoneFile(); + if (fileToPlay) fileToPlay->getNext (out, writableSize/sizeof (SFLDataFormat), 100); - pa_stream_write (ringtone_->pulseStream(), out, writableSize, NULL, 0, PA_SEEK_RELATIVE); - - pa_xfree (out); - } - else { - - if (ringtone_->getStreamState() != PA_STREAM_READY) { - _error("PulseAudio: Error: Ringtone stream not in state ready"); - return; - } - - SFLDataFormat *out = (SFLDataFormat*) pa_xmalloc (writableSize); + else memset (out, 0, writableSize); - pa_stream_write (ringtone_->pulseStream(), out, writableSize, NULL, 0, PA_SEEK_RELATIVE); - - pa_xfree (out); - } + pa_stream_write (ringtone_->pulseStream(), out, writableSize, NULL, 0, PA_SEEK_RELATIVE); + pa_xfree (out); } - -static void retrieve_server_info (pa_context *c UNUSED, const pa_server_info *i, void *userdata UNUSED) -{ - _debug ("Server Info: Process owner : %s" , i->user_name); - _debug ("\t\tServer name : %s - Server version = %s" , i->server_name, i->server_version); - _debug ("\t\tDefault sink name : %s" , i->default_sink_name); - _debug ("\t\tDefault source name : %s" , i->default_source_name); -} - -static void reduce_sink_list_cb (pa_context *c UNUSED, const pa_sink_input_info *i, int eol, void *userdata) -{ - PulseLayer* pulse = (PulseLayer*) userdata; - - if (!eol) { - //_debug("Sink Info: index : %i" , i->index); - //_debug("\t\tClient : %i" , i->client); - //_debug("\t\tVolume : %i" , i->volume.values[0]); - //_debug("\t\tChannels : %i" , i->volume.channels); - if (strcmp (i->name , PLAYBACK_STREAM_NAME) != 0) - pulse->setSinkVolume (i->index , i->volume.channels, 10); - } -} - -static void restore_sink_list_cb (pa_context *c UNUSED, const pa_sink_input_info *i, int eol, void *userdata) -{ - PulseLayer* pulse = (PulseLayer*) userdata; - - if (!eol) { - //_debug("Sink Info: index : %i" , i->index); - //_debug("\t\tSink name : -%s-" , i->name); - //_debug("\t\tClient : %i" , i->client); - //_debug("\t\tVolume : %i" , i->volume.values[0]); - //_debug("\t\tChannels : %i" , i->volume.channels); - if (strcmp (i->name , PLAYBACK_STREAM_NAME) != 0) - pulse->setSinkVolume (i->index , i->volume.channels, 100); - } -} - -static void set_playback_volume_cb (pa_context *c UNUSED, const pa_sink_input_info *i, int eol, void *userdata) -{ - PulseLayer* pulse; - int volume; - - pulse = (PulseLayer*) userdata; - volume = pulse->getSpkrVolume(); - - if (!eol) { - if (strcmp (i->name , PLAYBACK_STREAM_NAME) == 0) - pulse->setSinkVolume (i->index , i->volume.channels, volume); - } -} - -static void set_capture_volume_cb (pa_context *c UNUSED, const pa_source_output_info *i, int eol, void *userdata) -{ - PulseLayer* pulse; - int volume; - - pulse = (PulseLayer*) userdata; - volume = pulse->getMicVolume(); - - if (!eol) { - if (strcmp (i->name , CAPTURE_STREAM_NAME) == 0) - pulse->setSourceVolume (i->index , i->channel_map.channels, volume); - } -} - -void -PulseLayer::reducePulseAppsVolume (void) -{ - pa_context_get_sink_input_info_list (context_, reduce_sink_list_cb , this); -} - -void -PulseLayer::restorePulseAppsVolume (void) -{ - pa_context_get_sink_input_info_list (context_, restore_sink_list_cb , this); -} - -void -PulseLayer::serverinfo (void) -{ - pa_context_get_server_info (context_, retrieve_server_info , NULL); -} - - -void PulseLayer::setSinkVolume (int index, int channels, int volume) -{ - pa_cvolume cvolume; - pa_volume_t vol = PA_VOLUME_NORM * ( (double) volume / 100) ; - - pa_cvolume_set (&cvolume , channels , vol); - _debug ("Set sink volume of index %i" , index); - pa_context_set_sink_input_volume (context_, index, &cvolume, NULL, NULL) ; - -} - -void PulseLayer::setSourceVolume (int index, int channels, int volume) -{ - - pa_cvolume cvolume; - pa_volume_t vol = PA_VOLUME_NORM * ( (double) volume / 100) ; - - pa_cvolume_set (&cvolume , channels , vol); - _debug ("Set source volume of index %i" , index); - pa_context_set_source_volume_by_index (context_, index, &cvolume, NULL, NULL); -} - - -void PulseLayer::setPlaybackVolume (int volume) -{ - setSpkrVolume (volume); - pa_context_get_sink_input_info_list (context_, set_playback_volume_cb , this); -} - -void PulseLayer::setCaptureVolume (int volume) -{ - setMicVolume (volume); - pa_context_get_source_output_info_list (context_, set_capture_volume_cb , this); -} - diff --git a/daemon/src/audio/pulseaudio/pulselayer.h b/daemon/src/audio/pulseaudio/pulselayer.h index 8c4baf6b4..c1ab15790 100644 --- a/daemon/src/audio/pulseaudio/pulselayer.h +++ b/daemon/src/audio/pulseaudio/pulselayer.h @@ -79,25 +79,6 @@ class PulseLayer : public AudioLayer static void context_state_callback (pa_context* c, void* user_data); - /** - * Reduce volume of every audio applications connected to the same sink - */ - void reducePulseAppsVolume (void); - - /** - * Restore the volume of every audio applications connected to the same sink to PA_VOLUME_NORM - */ - void restorePulseAppsVolume (void); - - /** - * Set the volume of a sink. - * @param index The index of the stream - * @param channels The stream's number of channels - * @param volume The new volume (between 0 and 100) - */ - void setSinkVolume (int index, int channels, int volume); - void setSourceVolume (int index, int channels, int volume); - void setPlaybackVolume (int volume); void setCaptureVolume (int volume); @@ -184,11 +165,6 @@ class PulseLayer : public AudioLayer */ void disconnectAudioStream (void); - /** - * Get some information about the pulseaudio server - */ - void serverinfo (void); - /** PulseAudio context and asynchronous loop */ pa_context* context_; pa_threaded_mainloop* mainloop_; diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index db70ee452..913ecbec1 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -2541,25 +2541,13 @@ void ManagerImpl::audioSamplingRateChanged (int samplerate) */ void ManagerImpl::initVolume () { - _debug ("Initiate Volume"); setSpkrVolume (audioPreference.getVolumespkr()); setMicVolume (audioPreference.getVolumemic()); } void ManagerImpl::setSpkrVolume (unsigned short spkr_vol) { - /* Set the manager sound volume */ _spkr_volume = spkr_vol; - - audioLayerMutexLock(); - - /* Only for PulseAudio */ - PulseLayer *pulselayer = dynamic_cast (_audiodriver); - - if (pulselayer and pulselayer->getLayerType() == PULSEAUDIO) - pulselayer->setPlaybackVolume (spkr_vol); - - audioLayerMutexUnlock(); } void ManagerImpl::setMicVolume (unsigned short mic_vol) @@ -2569,9 +2557,7 @@ void ManagerImpl::setMicVolume (unsigned short mic_vol) int ManagerImpl::getLocalIp2IpPort (void) const { - // The SIP port used for default account (IP to IP) calls= return preferences.getPortNum(); - }