Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-daemon
Commits
e32ac62f
Commit
e32ac62f
authored
Aug 30, 2011
by
Rafaël Carré
Browse files
* #6629 : simplify AudioLayer creation
Move ALSA specific options to alsalayer only
parent
073bfc05
Changes
9
Hide whitespace changes
Inline
Side-by-side
daemon/src/audio/alsa/alsalayer.cpp
View file @
e32ac62f
...
...
@@ -74,11 +74,14 @@ void AlsaThread::run (void)
// Constructor
AlsaLayer
::
AlsaLayer
()
:
AudioLayer
(
ALSA
)
,
indexIn_
(
audioPref
.
getCardin
())
,
indexOut_
(
audioPref
.
getCardout
())
,
indexRing_
(
audioPref
.
getCardring
())
,
playbackHandle_
(
NULL
)
,
ringtoneHandle_
(
NULL
)
,
captureHandle_
(
NULL
)
,
periodSize_
(
160
)
,
audioPlugin_
(
"default"
)
,
audioPlugin_
(
audioPref
.
getPlugin
()
)
,
IDSoundCards_
()
,
is_playback_prepared_
(
false
)
,
is_capture_prepared_
(
false
)
...
...
@@ -88,85 +91,30 @@ AlsaLayer::AlsaLayer ()
,
is_capture_open_
(
false
)
,
trigger_request_
(
false
)
,
audioThread_
(
NULL
)
,
converter_
(
0
)
{
_debug
(
"Audio: Build ALSA layer"
);
urgentRingBuffer_
.
createReadPointer
();
audioPlugin_
=
audioPref
.
getPlugin
();
}
// Destructor
AlsaLayer
::~
AlsaLayer
(
void
)
{
_debug
(
"Audio: Destroy of ALSA layer"
);
closeLayer
();
delete
converter_
;
}
void
AlsaLayer
::
closeLayer
()
{
_debug
(
"Audio: Close ALSA streams"
);
try
{
/* Stop the audio thread first */
if
(
audioThread_
)
{
_debug
(
"Audio: Stop Audio Thread"
);
delete
audioThread_
;
audioThread_
=
NULL
;
}
}
catch
(...)
{
_debug
(
"Audio: Exception: when stopping audiortp"
);
throw
;
}
delete
audioThread_
;
/* Then close the audio devices */
closeCaptureStream
();
closePlaybackStream
();
captureHandle_
=
NULL
;
playbackHandle_
=
NULL
;
ringtoneHandle_
=
NULL
;
}
void
AlsaLayer
::
openDevice
(
int
indexIn
,
int
indexOut
,
int
indexRing
,
int
sampleRate
,
int
stream
,
const
std
::
string
&
plugin
)
void
AlsaLayer
::
setPlugin
(
const
std
::
string
&
plugin
)
{
/* Close the devices before open it */
if
(
stream
==
SFL_PCM_BOTH
and
is_capture_open_
and
is_playback_open_
)
{
closeCaptureStream
();
closePlaybackStream
();
}
else
if
(
(
stream
==
SFL_PCM_CAPTURE
or
stream
==
SFL_PCM_BOTH
)
and
is_capture_open_
)
closeCaptureStream
();
else
if
(
(
stream
==
SFL_PCM_PLAYBACK
or
stream
==
SFL_PCM_BOTH
)
and
is_playback_open_
)
closePlaybackStream
();
indexIn_
=
indexIn
;
indexOut_
=
indexOut
;
indexRing_
=
indexRing
;
audioSampleRate_
=
sampleRate
;
audioPlugin_
=
plugin
;
_debug
(
" Setting AlsaLayer: device in=%2d, out=%2d, ring=%2d"
,
indexIn_
,
indexOut_
,
indexRing_
);
_debug
(
" : alsa plugin=%s"
,
audioPlugin_
.
c_str
());
_debug
(
" : sample rate=%5d, format=%s"
,
audioSampleRate_
,
SFLDataFormatString
);
audioThread_
=
NULL
;
// use 1 sec buffer for resampling
converter_
=
new
SamplerateConverter
(
audioSampleRate_
);
delete
audioThread_
;
audioThread_
=
NULL
;
// FIXME : restart audio thread
}
void
AlsaLayer
::
startStream
(
void
)
{
_debug
(
"Audio: Start stream"
);
dcblocker_
.
reset
();
if
(
is_playback_running_
and
is_capture_running_
)
...
...
@@ -190,12 +138,55 @@ AlsaLayer::startStream (void)
_debug
(
"pcmr: %s, index %d"
,
pcmr
.
c_str
(),
indexRing_
);
_debug
(
"pcmc: %s, index %d"
,
pcmc
.
c_str
(),
indexIn_
);
if
(
not
is_capture_open_
)
open_device
(
pcmp
,
pcmc
,
pcmr
,
SFL_PCM_CAPTURE
);
if
(
not
is_capture_open_
)
{
_debug
(
"Audio: Open capture device"
);
if
(
not
is_playback_open_
)
open_device
(
pcmp
,
pcmc
,
pcmr
,
SFL_PCM_PLAYBACK
);
if
(
snd_pcm_open
(
&
captureHandle_
,
pcmc
.
c_str
(),
SND_PCM_STREAM_CAPTURE
,
0
)
<
0
)
{
_warn
(
"Audio: Error: Opening capture device %s"
,
pcmc
.
c_str
()
);
Manager
::
instance
().
getDbusManager
()
->
getConfigurationManager
()
->
errorAlert
(
ALSA_CAPTURE_DEVICE
);
is_capture_open_
=
false
;
}
if
(
!
alsa_set_params
(
captureHandle_
,
0
))
{
_warn
(
"Audio: Error: Capture failed"
);
snd_pcm_close
(
captureHandle_
);
is_capture_open_
=
false
;
}
is_capture_open_
=
true
;
}
if
(
not
is_playback_open_
)
{
_debug
(
"Audio: Open playback device (and ringtone)"
);
int
err
;
if
((
err
=
snd_pcm_open
(
&
playbackHandle_
,
pcmp
.
c_str
(),
SND_PCM_STREAM_PLAYBACK
,
0
))
<
0
)
{
_warn
(
"Audio: Error while opening playback device %s"
,
pcmp
.
c_str
());
Manager
::
instance
().
getDbusManager
()
->
getConfigurationManager
()
->
errorAlert
(
ALSA_PLAYBACK_DEVICE
);
is_playback_open_
=
false
;
}
if
(
!
alsa_set_params
(
playbackHandle_
,
1
))
{
_warn
(
"Audio: Error: Playback failed"
);
snd_pcm_close
(
playbackHandle_
);
is_playback_open_
=
false
;
}
if
(
getIndexOut
()
!=
getIndexRing
())
{
if
((
err
=
snd_pcm_open
(
&
ringtoneHandle_
,
pcmr
.
c_str
(),
SND_PCM_STREAM_PLAYBACK
,
0
))
<
0
)
_warn
(
"Audio: Error: Opening ringtone device %s"
,
pcmr
.
c_str
());
if
(
!
alsa_set_params
(
ringtoneHandle_
,
1
))
{
_warn
(
"Audio: Error: Ringtone failed"
);
snd_pcm_close
(
ringtoneHandle_
);
}
}
is_playback_open_
=
true
;
}
prepareCaptureStream
();
preparePlaybackStream
();
...
...
@@ -225,17 +216,8 @@ AlsaLayer::stopStream (void)
isStarted_
=
false
;
try
{
/* Stop the audio thread first */
if
(
audioThread_
)
{
_debug
(
"Audio: Stop audio thread"
);
delete
audioThread_
;
audioThread_
=
NULL
;
}
}
catch
(...)
{
_debug
(
"Audio: Exception: when stopping audiortp"
);
throw
;
}
delete
audioThread_
;
audioThread_
=
NULL
;
closeCaptureStream
();
closePlaybackStream
();
...
...
@@ -268,6 +250,32 @@ void AlsaLayer::stopCaptureStream (void)
}
}
void
AlsaLayer
::
setIndexRing
(
int
index
)
{
indexRing_
=
index
;
delete
audioThread_
;
audioThread_
=
NULL
;
}
void
AlsaLayer
::
setIndexOut
(
int
index
)
{
indexOut_
=
index
;
if
(
is_playback_open_
)
closePlaybackStream
();
delete
audioThread_
;
audioThread_
=
NULL
;
}
void
AlsaLayer
::
setIndexIn
(
int
index
)
{
indexIn_
=
index
;
if
(
is_capture_open_
)
closeCaptureStream
();
delete
audioThread_
;
audioThread_
=
NULL
;
}
void
AlsaLayer
::
closeCaptureStream
(
void
)
{
if
(
is_capture_prepared_
and
is_capture_running_
)
...
...
@@ -427,7 +435,8 @@ bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle, int type)
if
(
dir
!=
0
)
{
_debug
(
"Audio: Error: (%i) The chosen rate %d Hz is not supported by your hardware.Using %d Hz instead. "
,
type
,
audioSampleRate_
,
exact_ivalue
);
audioSampleRate_
=
exact_ivalue
;
//audioSampleRate_ = exact_ivalue;
// FIXME
}
/* Set the number of channels */
...
...
@@ -493,68 +502,6 @@ bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle, int type)
return
true
;
}
bool
AlsaLayer
::
open_device
(
std
::
string
pcm_p
,
std
::
string
pcm_c
,
std
::
string
pcm_r
,
int
flag
)
{
if
(
flag
==
SFL_PCM_BOTH
or
flag
==
SFL_PCM_PLAYBACK
)
{
_debug
(
"Audio: Open playback device (and ringtone)"
);
int
err
;
if
((
err
=
snd_pcm_open
(
&
playbackHandle_
,
pcm_p
.
c_str
(),
SND_PCM_STREAM_PLAYBACK
,
0
))
<
0
)
{
_warn
(
"Audio: Error while opening playback device %s"
,
pcm_p
.
c_str
());
Manager
::
instance
().
getDbusManager
()
->
getConfigurationManager
()
->
errorAlert
(
ALSA_PLAYBACK_DEVICE
);
is_playback_open_
=
false
;
return
false
;
}
if
(
!
alsa_set_params
(
playbackHandle_
,
1
))
{
_warn
(
"Audio: Error: Playback failed"
);
snd_pcm_close
(
playbackHandle_
);
is_playback_open_
=
false
;
return
false
;
}
if
(
getIndexOut
()
!=
getIndexRing
())
{
if
((
err
=
snd_pcm_open
(
&
ringtoneHandle_
,
pcm_r
.
c_str
(),
SND_PCM_STREAM_PLAYBACK
,
0
))
<
0
)
_warn
(
"Audio: Error: Opening ringtone device %s"
,
pcm_r
.
c_str
());
if
(
!
alsa_set_params
(
ringtoneHandle_
,
1
))
{
_warn
(
"Audio: Error: Ringtone failed"
);
snd_pcm_close
(
ringtoneHandle_
);
}
}
is_playback_open_
=
true
;
}
if
(
flag
==
SFL_PCM_BOTH
or
flag
==
SFL_PCM_CAPTURE
)
{
_debug
(
"Audio: Open capture device"
);
if
(
snd_pcm_open
(
&
captureHandle_
,
pcm_c
.
c_str
(),
SND_PCM_STREAM_CAPTURE
,
0
)
<
0
)
{
_warn
(
"Audio: Error: Opening capture device %s"
,
pcm_c
.
c_str
());
Manager
::
instance
().
getDbusManager
()
->
getConfigurationManager
()
->
errorAlert
(
ALSA_CAPTURE_DEVICE
);
is_capture_open_
=
false
;
return
false
;
}
if
(
!
alsa_set_params
(
captureHandle_
,
0
))
{
_warn
(
"Audio: Error: Capture failed"
);
snd_pcm_close
(
captureHandle_
);
is_capture_open_
=
false
;
return
false
;
}
is_capture_open_
=
true
;
}
return
true
;
}
//TODO first frame causes broken pipe (underrun) because not enough data are send --> make the handle wait to be ready
int
AlsaLayer
::
write
(
void
*
buffer
,
int
length
,
snd_pcm_t
*
handle
)
...
...
daemon/src/audio/alsa/alsalayer.h
View file @
e32ac62f
...
...
@@ -35,7 +35,6 @@
#include
"audio/audiolayer.h"
#include
<alsa/asoundlib.h>
class
SamplerateConverter
;
class
RingBuffer
;
class
ManagerImpl
;
class
AlsaThread
;
...
...
@@ -58,20 +57,6 @@ class AlsaLayer : public AudioLayer
*/
~
AlsaLayer
(
void
);
/**
* Check if no devices are opened, otherwise close them.
* Then open the specified devices by calling the private functions open_device
* @param indexIn The number of the card chosen for capture
* @param indexOut The number of the card chosen for playback
* @param sampleRate The sample rate
* @param stream To indicate which kind of stream you want to open
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @param plugin The alsa plugin ( dmix , default , front , surround , ...)
*/
void
openDevice
(
int
indexIn
,
int
indexOut
,
int
indexRing
,
int
sampleRate
,
int
stream
,
const
std
::
string
&
plugin
);
/**
* Start the capture stream and prepare the playback stream.
* The playback starts accordingly to its threshold
...
...
@@ -123,7 +108,7 @@ class AlsaLayer : public AudioLayer
* @return bool True if it exists and supports the mode
* false otherwise
*/
bool
soundCardIndexExist
(
int
card
,
int
stream
);
static
bool
soundCardIndexExist
(
int
card
,
int
stream
);
/**
* An index is associated with its string description
...
...
@@ -142,9 +127,55 @@ class AlsaLayer : public AudioLayer
void
audioCallback
(
void
);
/**
* Get the index of the audio card for capture
* @return int The index of the card used for capture
* 0 for the first available card on the system, 1 ...
*/
int
getIndexIn
()
const
{
return
indexIn_
;
}
void
setIndexIn
(
int
);
/**
* Get the index of the audio card for playback
* @return int The index of the card used for playback
* 0 for the first available card on the system, 1 ...
*/
int
getIndexOut
()
const
{
return
indexOut_
;
}
void
setIndexOut
(
int
);
/**
* Get the index of the audio card for ringtone (could be differnet from playback)
* @return int The index of the card used for ringtone
* 0 for the first available card on the system, 1 ...
*/
int
getIndexRing
()
const
{
return
indexRing_
;
}
void
setIndexRing
(
int
);
void
setPlugin
(
const
std
::
string
&
plugin
);
private:
void
closeLayer
(
void
);
/**
* Number of audio cards on which capture stream has been opened
*/
int
indexIn_
;
/**
* Number of audio cards on which playback stream has been opened
*/
int
indexOut_
;
/**
* Number of audio cards on which ringtone stream has been opened
*/
int
indexRing_
;
/** Associate a sound card index to its string description */
typedef
std
::
pair
<
int
,
std
::
string
>
HwIDPair
;
...
...
@@ -170,20 +201,6 @@ class AlsaLayer : public AudioLayer
void
startPlaybackStream
(
void
);
void
preparePlaybackStream
(
void
);
/**
* Open the specified device.
* ALSA Library API
* @param pcm_p The string name for the playback device
* @param pcm_c The string name for the capture device
* @param flag To indicate which kind of stream you want to open
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @return true if successful
* false otherwise
*/
bool
open_device
(
std
::
string
pcm_p
,
std
::
string
pcm_c
,
std
::
string
pcm_r
,
int
flag
);
bool
alsa_set_params
(
snd_pcm_t
*
pcm_handle
,
int
type
);
/**
...
...
@@ -256,9 +273,6 @@ class AlsaLayer : public AudioLayer
bool
trigger_request_
;
AlsaThread
*
audioThread_
;
/** Sample rate converter object */
SamplerateConverter
*
converter_
;
};
#endif // _ALSA_LAYER_H_
daemon/src/audio/audiolayer.cpp
View file @
e32ac62f
...
...
@@ -37,20 +37,20 @@
AudioLayer
::
AudioLayer
(
int
type
)
:
isStarted_
(
false
)
,
urgentRingBuffer_
(
SIZEBUF
,
Call
::
DEFAULT_ID
)
,
recorder_
(
0
)
,
indexIn_
(
0
)
,
indexOut_
(
0
)
,
indexRing_
(
0
)
,
audioSampleRate_
(
0
)
,
audioSampleRate_
(
Manager
::
instance
().
getMainBuffer
()
->
getInternalSamplingRate
())
,
mutex_
()
,
audioPref
(
Manager
::
instance
().
audioPreference
)
,
converter_
(
new
SamplerateConverter
(
audioSampleRate_
))
,
layerType_
(
type
)
,
lastNotificationTime_
(
0
)
{}
{
urgentRingBuffer_
.
createReadPointer
();
}
AudioLayer
::~
AudioLayer
()
{
delete
converter_
;
}
void
AudioLayer
::
flushMain
(
void
)
...
...
daemon/src/audio/audiolayer.h
View file @
e32ac62f
...
...
@@ -40,6 +40,7 @@
#include
"manager.h"
#include
"ringbuffer.h"
#include
"dcblocker.h"
#include
"samplerateconverter.h"
/**
* @file audiolayer.h
...
...
@@ -72,20 +73,6 @@ class AudioLayer
*/
virtual
~
AudioLayer
(
void
);
/**
* Check if no devices are opened, otherwise close them.
* Then open the specified devices by calling the private functions open_device
* @param indexIn The number of the card chosen for capture
* @param indexOut The number of the card chosen for playback
* @param sampleRate The sample rate
* @param stream To indicate which kind of stream you want to open
* SFL_PCM_CAPTURE
* SFL_PCM_PLAYBACK
* SFL_PCM_BOTH
* @param plugin The alsa plugin ( dmix , default , front , surround , ...)
*/
virtual
void
openDevice
(
int
indexIn
,
int
indexOut
,
int
indexRing
,
int
sampleRate
,
int
stream
,
const
std
::
string
&
plugin
)
=
0
;
/**
* Start the capture stream and prepare the playback stream.
* The playback starts accordingly to its threshold
...
...
@@ -114,32 +101,6 @@ class AudioLayer
void
flushUrgent
(
void
);
/**
* Get the index of the audio card for capture
* @return int The index of the card used for capture
* 0 for the first available card on the system, 1 ...
*/
int
getIndexIn
()
const
{
return
indexIn_
;
}
/**
* Get the index of the audio card for playback
* @return int The index of the card used for playback
* 0 for the first available card on the system, 1 ...
*/
int
getIndexOut
()
const
{
return
indexOut_
;
}
/**
* Get the index of the audio card for ringtone (could be differnet from playback)
* @return int The index of the card used for ringtone
* 0 for the first available card on the system, 1 ...
*/
int
getIndexRing
()
const
{
return
indexRing_
;
}
/**
* Get the sample rate of the audio layer
...
...
@@ -171,20 +132,6 @@ class AudioLayer
return
Manager
::
instance
().
getMainBuffer
();
}
/**
* Set the audio recorder
*/
void
setRecorderInstance
(
Recordable
*
rec
)
{
recorder_
=
rec
;
}
/**
* Get the audio recorder
*/
Recordable
*
getRecorderInstance
(
void
)
const
{
return
recorder_
;
}
/**
* Get the mutex lock for the entire audio layer
*/
...
...
@@ -216,31 +163,11 @@ class AudioLayer
*/
RingBuffer
urgentRingBuffer_
;
/**
* A pointer to the recordable instance (may be a call or a conference)
*/
Recordable
*
recorder_
;
/**
* Number of audio cards on which capture stream has been opened
*/
int
indexIn_
;
/**
* Number of audio cards on which playback stream has been opened
*/
int
indexOut_
;
/**
* Number of audio cards on which ringtone stream has been opened
*/
int
indexRing_
;
/**
* Sample Rate SFLphone should send sound data to the sound card
* The value can be set in the user config file- now: 44100HZ
*/
unsigned
int
audioSampleRate_
;
const
unsigned
int
audioSampleRate_
;
/**
* Lock for the entire audio layer
...
...
@@ -251,6 +178,8 @@ class AudioLayer
AudioPreference
&
audioPref
;
SamplerateConverter
*
converter_
;
private:
const
int
layerType_
;
...
...
daemon/src/audio/pulseaudio/pulselayer.cpp
View file @
e32ac62f
...
...
@@ -219,45 +219,41 @@ void playback_overflow_callback (pa_stream* s UNUSED, void* userdata UNUSED)
PulseLayer
::
PulseLayer
()
:
AudioLayer
(
PULSEAUDIO
)
,
context_
(
0
)
,
mainloop_
(
0
)
,
playback_
(
0
)
,
record_
(
0
)
,
ringtone_
(
0
)
,
converter_
(
0
)
{
urgentRingBuffer_
.
createReadPointer
(
);
setenv
(
"PULSE_PROP_media.role"
,
"phone"
,
1
);
openLayer
();
}
mainloop_
=
pa_threaded_mainloop_new
();
if
(
!
mainloop_
)
_error
(
"Couldn't create pulseaudio mainloop"
);
// Destructor
PulseLayer
::~
PulseLayer
(
void
)
{
closeLayer
();
delete
converter_
;
}
context_
=
pa_context_new
(
pa_threaded_mainloop_get_api
(
mainloop_
)
,
"SFLphone"
);
if
(
!
context_
)
_error
(
"Couldn't create pulseaudio context"
);
void
PulseLayer
::
openLayer
(
void
)
{
if
(
isStarted_
)
return
;
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"
);
pa_threaded_mainloop_lock
(
mainloop_
);
if
(
pa_threaded_mainloop_start
(
mainloop_
)
<
0
)
_error
(
"Failed to start pulseaudio mainloop"
);
pa_threaded_mainloop_wait
(
mainloop_
);
_info
(
"Audio: Open Pulseaudio layer"
);
if
(
pa_context_get_state
(
context_
)
!=
PA_CONTEXT_READY
)
_error
(
"Couldn't connect to pulse audio server"
);
connectPulseAudioServer
(
);