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
6fedd707
Commit
6fedd707
authored
Aug 30, 2011
by
Rafaël Carré
Browse files
* #6629: Always restart audio driver when changing parameters (ALSA only)
parent
b4558a88
Changes
6
Hide whitespace changes
Inline
Side-by-side
daemon/src/audio/alsa/alsalayer.cpp
View file @
6fedd707
...
...
@@ -104,12 +104,20 @@ AlsaLayer::~AlsaLayer (void)
closePlaybackStream
();
}
void
AlsaLayer
::
setPlugin
(
const
std
::
string
&
plugin
)
bool
AlsaLayer
::
openDevice
(
snd_pcm_t
**
pcm
,
const
std
::
string
&
dev
,
snd_pcm_stream_t
stream
)
{
audioPlugin_
=
plugin
;
delete
audioThread_
;
audioThread_
=
NULL
;
// FIXME : restart audio thread
int
err
=
snd_pcm_open
(
pcm
,
dev
.
c_str
(),
stream
,
0
);
if
(
err
<
0
)
{
_error
(
"Alsa: couldn't open device %s : %s"
,
dev
.
c_str
(),
snd_strerror
(
err
));
return
false
;
}
if
(
!
alsa_set_params
(
*
pcm
))
{
snd_pcm_close
(
*
pcm
);
return
false
;
}
return
true
;
}
void
...
...
@@ -125,13 +133,13 @@ AlsaLayer::startStream (void)
std
::
string
pcmc
;
if
(
audioPlugin_
==
PCM_DMIX_DSNOOP
)
{
pcmp
=
buildDeviceTopo
(
PCM_DMIX
,
indexOut_
,
0
);
pcmr
=
buildDeviceTopo
(
PCM_DMIX
,
indexRing_
,
0
);
pcmc
=
buildDeviceTopo
(
PCM_DSNOOP
,
indexIn_
,
0
);
pcmp
=
buildDeviceTopo
(
PCM_DMIX
,
indexOut_
);
pcmr
=
buildDeviceTopo
(
PCM_DMIX
,
indexRing_
);
pcmc
=
buildDeviceTopo
(
PCM_DSNOOP
,
indexIn_
);
}
else
{
pcmp
=
buildDeviceTopo
(
audioPlugin_
,
indexOut_
,
0
);
pcmr
=
buildDeviceTopo
(
audioPlugin_
,
indexRing_
,
0
);
pcmc
=
buildDeviceTopo
(
audioPlugin_
,
indexIn_
,
0
);
pcmp
=
buildDeviceTopo
(
audioPlugin_
,
indexOut_
);
pcmr
=
buildDeviceTopo
(
audioPlugin_
,
indexRing_
);
pcmc
=
buildDeviceTopo
(
audioPlugin_
,
indexIn_
);
}
_debug
(
"pcmp: %s, index %d"
,
pcmp
.
c_str
(),
indexOut_
);
...
...
@@ -139,54 +147,22 @@ AlsaLayer::startStream (void)
_debug
(
"pcmc: %s, index %d"
,
pcmc
.
c_str
(),
indexIn_
);
if
(
not
is_capture_open_
)
{
_debug
(
"Audio: Open capture device"
);
if
(
snd_pcm_open
(
&
captureHandle_
,
pcmc
.
c_str
(),
SND_PCM_STREAM_CAPTURE
,
0
)
<
0
)
{
_warn
(
"Audio: Error: Opening capture device %s"
,
pcmc
.
c_str
());
is_capture_open_
=
openDevice
(
&
captureHandle_
,
pcmc
,
SND_PCM_STREAM_CAPTURE
);
if
(
not
is_capture_open_
)
{
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
());
is_playback_open_
=
openDevice
(
&
playbackHandle_
,
pcmp
,
SND_PCM_STREAM_PLAYBACK
);
if
(
not
is_playback_open_
)
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
;
if
(
getIndexOut
()
!=
getIndexRing
())
if
(
!
openDevice
(
&
ringtoneHandle_
,
pcmr
,
SND_PCM_STREAM_PLAYBACK
))
Manager
::
instance
().
getDbusManager
()
->
getConfigurationManager
()
->
errorAlert
(
ALSA_PLAYBACK_DEVICE
);
}
prepareCaptureStream
();
preparePlaybackStream
();
...
...
@@ -197,13 +173,8 @@ AlsaLayer::startStream (void)
flushUrgent
();
if
(
audioThread_
==
NULL
)
{
try
{
_debug
(
"Audio: Start Audio Thread"
);
audioThread_
=
new
AlsaThread
(
this
);
audioThread_
->
start
();
}
catch
(...)
{
_debug
(
"Fail to start audio thread"
);
}
audioThread_
=
new
AlsaThread
(
this
);
audioThread_
->
start
();
}
isStarted_
=
true
;
...
...
@@ -250,32 +221,6 @@ 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_
)
...
...
@@ -389,7 +334,7 @@ void AlsaLayer::preparePlaybackStream (void)
}
}
bool
AlsaLayer
::
alsa_set_params
(
snd_pcm_t
*
pcm_handle
,
int
type
)
bool
AlsaLayer
::
alsa_set_params
(
snd_pcm_t
*
pcm_handle
)
{
snd_pcm_hw_params_t
*
hwparams
=
NULL
;
snd_pcm_sw_params_t
*
swparams
=
NULL
;
...
...
@@ -428,13 +373,13 @@ bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle, int type)
unsigned
int
exact_ivalue
=
audioSampleRate_
;
if
((
err
=
snd_pcm_hw_params_set_rate_near
(
pcm_handle
,
hwparams
,
&
exact_ivalue
,
&
dir
)
<
0
))
{
_
debug
(
"Audio: Error
: Cannot set sample rate (%s)"
,
snd_strerror
(
err
));
_
error
(
"Alsa
: Cannot set sample rate (%s)"
,
snd_strerror
(
err
));
return
false
;
}
else
_debug
(
"A
udio
: Set audio rate to %d"
,
audioSampleRate_
);
_debug
(
"A
lsa
: Set audio rate to %d"
,
audioSampleRate_
);
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
);
_
error
(
"Alsa:
The chosen rate %d Hz is not supported by your hardware.Using %d Hz instead. "
,
audioSampleRate_
,
exact_ivalue
);
//audioSampleRate_ = exact_ivalue;
// FIXME
}
...
...
@@ -456,7 +401,7 @@ bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle, int type)
}
if
(
dir
!=
0
)
_
debug
(
"Audio: Warning: (%i)
The chosen period size %lu bytes is not supported by your hardware.Using %lu instead. "
,
type
,
periodsize
,
exact_lvalue
);
_
warn
(
"Alsa:
The chosen period size %lu bytes is not supported by your hardware.Using %lu instead. "
,
periodsize
,
exact_lvalue
);
periodSize_
=
exact_lvalue
;
/* Set the number of fragments */
...
...
@@ -619,36 +564,22 @@ AlsaLayer::handle_xrun_playback (snd_pcm_t *handle)
}
std
::
string
AlsaLayer
::
buildDeviceTopo
(
const
std
::
string
&
plugin
,
int
card
,
int
subdevice
)
AlsaLayer
::
buildDeviceTopo
(
const
std
::
string
&
plugin
,
int
card
)
{
std
::
stringstream
ss
,
ss1
;
std
::
stringstream
ss
;
std
::
string
pcm
(
plugin
);
if
(
pcm
==
PCM_DEFAULT
)
return
pcm
;
ss
<<
card
;
ss
<<
":"
<<
card
;
pcm
.
append
(
":"
);
pcm
.
append
(
ss
.
str
());
if
(
subdevice
!=
0
)
{
pcm
.
append
(
","
);
ss1
<<
subdevice
;
pcm
.
append
(
ss1
.
str
());
}
_debug
(
"Audio: Device topo: %s"
,
pcm
.
c_str
());
return
pcm
;
return
pcm
+
ss
.
str
();
}
std
::
vector
<
std
::
string
>
AlsaLayer
::
getSoundCardsInfo
(
int
stream
)
{
_debug
(
"Audio: Get sound cards info: "
);
snd_ctl_t
*
handle
;
snd_ctl_card_info_t
*
info
;
snd_pcm_info_t
*
pcminfo
;
...
...
@@ -656,7 +587,6 @@ AlsaLayer::getSoundCardsInfo (int stream)
snd_pcm_info_alloca
(
&
pcminfo
);
int
numCard
=
-
1
;
std
::
string
description
;
std
::
vector
<
std
::
string
>
cards_id
;
if
(
snd_card_next
(
&
numCard
)
<
0
||
numCard
<
0
)
...
...
@@ -679,7 +609,7 @@ AlsaLayer::getSoundCardsInfo (int stream)
numCard
,
snd_ctl_card_info_get_id
(
info
),
snd_ctl_card_info_get_name
(
info
));
description
=
snd_ctl_card_info_get_name
(
info
);
std
::
string
description
=
snd_ctl_card_info_get_name
(
info
);
description
.
append
(
" - "
);
description
.
append
(
snd_pcm_info_get_name
(
pcminfo
));
cards_id
.
push_back
(
description
);
...
...
daemon/src/audio/alsa/alsalayer.h
View file @
6fedd707
...
...
@@ -83,10 +83,9 @@ class AlsaLayer : public AudioLayer
* Concatenate two strings. Used to build a valid pcm device name.
* @param plugin the alsa PCM name
* @param card the sound card number
* @param subdevice the subdevice number
* @return std::string the concatenated string
*/
std
::
string
buildDeviceTopo
(
const
std
::
string
&
plugin
,
int
card
,
int
subdevice
);
std
::
string
buildDeviceTopo
(
const
std
::
string
&
plugin
,
int
card
);
/**
* Scan the sound card available on the system
...
...
@@ -135,7 +134,6 @@ class AlsaLayer : public AudioLayer
int
getIndexIn
()
const
{
return
indexIn_
;
}
void
setIndexIn
(
int
);
/**
* Get the index of the audio card for playback
...
...
@@ -145,7 +143,6 @@ class AlsaLayer : public AudioLayer
int
getIndexOut
()
const
{
return
indexOut_
;
}
void
setIndexOut
(
int
);
/**
* Get the index of the audio card for ringtone (could be differnet from playback)
...
...
@@ -155,13 +152,12 @@ class AlsaLayer : public AudioLayer
int
getIndexRing
()
const
{
return
indexRing_
;
}
void
setIndexRing
(
int
);
void
setPlugin
(
const
std
::
string
&
plugin
);
private:
bool
openDevice
(
snd_pcm_t
**
pcm
,
const
std
::
string
&
dev
,
snd_pcm_stream_t
stream
);
/**
* Number of audio cards on which capture stream has been opened
*/
...
...
@@ -201,7 +197,7 @@ class AlsaLayer : public AudioLayer
void
startPlaybackStream
(
void
);
void
preparePlaybackStream
(
void
);
bool
alsa_set_params
(
snd_pcm_t
*
pcm_handle
,
int
type
);
bool
alsa_set_params
(
snd_pcm_t
*
pcm_handle
);
/**
* Copy a data buffer in the internal ring buffer
...
...
daemon/src/audio/audiolayer.h
View file @
6fedd707
...
...
@@ -142,19 +142,9 @@ class AudioLayer
void
notifyincomingCall
(
void
);
protected:
/**
* Drop the pending frames and close the capture device
*/
virtual
void
closeCaptureStream
(
void
)
=
0
;
/**
* Drop the pending frames and close the playback device
*/
virtual
void
closePlaybackStream
(
void
)
=
0
;
/**
* Wether or not the audio layer stream is started
* Wether or not the audio layer stream is started
*/
bool
isStarted_
;
...
...
daemon/src/audio/pulseaudio/pulselayer.cpp
View file @
6fedd707
...
...
@@ -310,21 +310,14 @@ void PulseLayer::context_state_callback (pa_context* c, void* user_data)
void
PulseLayer
::
updateSinkList
(
void
)
{
_debug
(
"Audio: Update sink list"
);
getSinkList
()
->
clear
();
pa_context_get_sink_info_list
(
context_
,
sink_input_info_callback
,
this
);
}
void
PulseLayer
::
updateSourceList
(
void
)
{
_debug
(
"Audio: Update source list"
);
getSourceList
()
->
clear
();
pa_context_get_source_info_list
(
context_
,
source_input_info_callback
,
this
);
}
bool
PulseLayer
::
inSinkList
(
const
std
::
string
&
deviceName
)
const
...
...
@@ -341,22 +334,15 @@ bool PulseLayer::inSourceList (const std::string &deviceName) const
void
PulseLayer
::
createStreams
(
pa_context
*
c
)
{
_info
(
"Audio: Create streams"
);
playback_
=
new
AudioStream
(
c
,
mainloop_
,
PLAYBACK_STREAM_NAME
,
PLAYBACK_STREAM
,
audioSampleRate_
);
std
::
string
playbackDevice
(
audioPref
.
getDevicePlayback
());
std
::
string
recordDevice
(
audioPref
.
getDeviceRecord
());
std
::
string
ringtoneDevice
(
audioPref
.
getDeviceRingtone
());
_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
());
_debug
(
"PulseAudio: Devices: playback %s , record %s , ringtone %s"
,
playbackDevice
.
c_str
(),
recordDevice
.
c_str
(),
ringtoneDevice
.
c_str
());
if
(
inSinkList
(
playbackDevice
))
playback_
->
connectStream
(
&
playbackDevice
);
else
playback_
->
connectStream
(
NULL
);
playback_
=
new
AudioStream
(
c
,
mainloop_
,
PLAYBACK_STREAM_NAME
,
PLAYBACK_STREAM
,
audioSampleRate_
);
playback_
->
connectStream
(
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
);
...
...
@@ -365,22 +351,14 @@ void PulseLayer::createStreams (pa_context* c)
pa_stream_set_latency_update_callback
(
playback_
->
pulseStream
(),
latency_update_callback
,
this
);
record_
=
new
AudioStream
(
c
,
mainloop_
,
CAPTURE_STREAM_NAME
,
CAPTURE_STREAM
,
audioSampleRate_
);
if
(
inSourceList
(
recordDevice
))
record_
->
connectStream
(
&
recordDevice
);
else
record_
->
connectStream
(
NULL
);
record_
->
connectStream
(
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_
);
if
(
inSourceList
(
ringtoneDevice
))
ringtone_
->
connectStream
(
&
ringtoneDevice
);
else
ringtone_
->
connectStream
(
NULL
);
ringtone_
->
connectStream
(
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
);
...
...
@@ -393,43 +371,13 @@ void PulseLayer::createStreams (pa_context* c)
void
PulseLayer
::
disconnectAudioStream
(
void
)
{
_info
(
"Audio: Disconnect audio stream"
);
closePlaybackStream
();
closeCaptureStream
();
}
void
PulseLayer
::
closeCaptureStream
(
void
)
{
if
(
record_
)
{
if
(
record_
->
pulseStream
())
{
const
char
*
name
=
pa_stream_get_device_name
(
record_
->
pulseStream
());
if
(
name
&&
strlen
(
name
))
{
_debug
(
"Audio: record device to be stored in config: %s"
,
name
);
audioPref
.
setDeviceRecord
(
name
);
}
}
delete
record_
;
record_
=
NULL
;
}
}
void
PulseLayer
::
closePlaybackStream
(
void
)
{
if
(
playback_
)
{
if
(
playback_
->
pulseStream
())
{
const
char
*
name
=
pa_stream_get_device_name
(
playback_
->
pulseStream
());
if
(
name
&&
strlen
(
name
))
{
_debug
(
"Audio: playback device to be stored in config: %s"
,
name
);
if
(
name
&&
*
name
)
audioPref
.
setDevicePlayback
(
name
);
}
}
delete
playback_
;
...
...
@@ -437,21 +385,28 @@ void PulseLayer::closePlaybackStream (void)
}
if
(
ringtone_
)
{
if
(
ringtone_
->
pulseStream
())
{
const
char
*
name
=
pa_stream_get_device_name
(
ringtone_
->
pulseStream
());
if
(
ringtone_
->
pulseStream
())
{
const
char
*
name
=
pa_stream_get_device_name
(
ringtone_
->
pulseStream
());
if
(
name
&&
*
name
)
audioPref
.
setDeviceRingtone
(
name
);
}
if
(
name
&&
strlen
(
name
))
{
_debug
(
"Audio: ringtone device to be stored in config: %s"
,
name
);
audioPref
.
setDeviceRingtone
(
name
);
}
}
delete
ringtone_
;
ringtone_
=
NULL
;
}
delete
ringtone_
;
ringtone_
=
NULL
;
if
(
record_
)
{
if
(
record_
->
pulseStream
())
{
const
char
*
name
=
pa_stream_get_device_name
(
record_
->
pulseStream
());
if
(
name
&&
*
name
)
audioPref
.
setDeviceRecord
(
name
);
}
delete
record_
;
record_
=
NULL
;
}
}
void
PulseLayer
::
startStream
(
void
)
{
// Create Streams
...
...
daemon/src/audio/pulseaudio/pulselayer.h
View file @
6fedd707
...
...
@@ -166,12 +166,6 @@ class PulseLayer : public AudioLayer
// Assignment Operator
PulseLayer
&
operator
=
(
const
PulseLayer
&
rh
);
/**
* Drop the pending frames and close the capture device
*/
void
closeCaptureStream
(
void
);
/**
* Write data from the ring buffer to the harware and read data from the hardware
*/
...
...
@@ -185,11 +179,6 @@ class PulseLayer : public AudioLayer
*/
void
createStreams
(
pa_context
*
c
);
/**
* Drop the pending frames and close the playback device
*/
void
closePlaybackStream
(
void
);
/**
* Close the connection with the local pulseaudio server
*/
...
...
daemon/src/managerimpl.cpp
View file @
6fedd707
...
...
@@ -2053,8 +2053,19 @@ void ManagerImpl::setAudioPlugin (const std::string& audioPlugin)
audioPreference
.
setPlugin
(
audioPlugin
);
AlsaLayer
*
alsa
=
dynamic_cast
<
AlsaLayer
*>
(
_audiodriver
);
if
(
alsa
)
alsa
->
setPlugin
(
audioPlugin
);
if
(
!
alsa
)
{
_error
(
"Can't find alsa device"
);
audioLayerMutexUnlock
();
return
;
}
bool
wasStarted
=
_audiodriver
->
isStarted
();
// Recreate audio driver with new settings
delete
_audiodriver
;
_audiodriver
=
new
AlsaLayer
;
if
(
wasStarted
)
_audiodriver
->
startStream
();
audioLayerMutexUnlock
();
}
...
...
@@ -2073,23 +2084,29 @@ void ManagerImpl::setAudioDevice (const int index, int streamType)
return
;
}
bool
wasStarted
=
_audiodriver
->
isStarted
();
switch
(
streamType
)
{
case
SFL_PCM_PLAYBACK
:
alsaLayer
->
setIndexOut
(
index
);
audioPreference
.
setCardout
(
index
);
break
;
case
SFL_PCM_CAPTURE
:
alsaLayer
->
setIndexIn
(
index
);
audioPreference
.
setCardin
(
index
);
break
;
case
SFL_PCM_RINGTONE
:
alsaLayer
->
setIndexRing
(
index
);
audioPreference
.
setCardring
(
index
);
break
;
default:
break
;
}
// Recreate audio driver with new settings
delete
_audiodriver
;
_audiodriver
=
new
AlsaLayer
;
if
(
wasStarted
)
_audiodriver
->
startStream
();
audioLayerMutexUnlock
();
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment