Commit 4d492670 authored by Alexandre Savard's avatar Alexandre Savard

[#1962] Bind pulseaudio stream to specific device (ringtone, playback, record)

Keep a list of activee device, open stream only if in list, fallback on default elsewhere
parent 9f462411
......@@ -47,12 +47,12 @@ AudioStream::~AudioStream()
}
bool
AudioStream::connectStream()
AudioStream::connectStream(std::string* deviceName)
{
ost::MutexLock guard (_mutex);
if (!_audiostream)
_audiostream = createStream (_context);
_audiostream = createStream (_context, deviceName);
return true;
}
......@@ -171,7 +171,7 @@ AudioStream::getStreamState (void)
pa_stream*
AudioStream::createStream (pa_context* c)
AudioStream::createStream (pa_context* c, std::string *deviceName)
{
ost::MutexLock guard (_mutex);
......@@ -196,18 +196,26 @@ AudioStream::createStream (pa_context* c)
attributes->tlength = pa_usec_to_bytes (100 * PA_USEC_PER_MSEC, &_sample_spec);
attributes->prebuf = 0;
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_lock(_mainloop);
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);
pa_threaded_mainloop_unlock(_mainloop);
} else if (_streamType == CAPTURE_STREAM) {
attributes->maxlength = (uint32_t) -1;
attributes->fragsize = pa_usec_to_bytes (50 * PA_USEC_PER_MSEC, &_sample_spec);
pa_threaded_mainloop_lock(_mainloop);
pa_stream_connect_record (s, NULL, attributes, (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY|PA_STREAM_AUTO_TIMING_UPDATE));
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) {
......
......@@ -81,7 +81,7 @@ class AudioStream {
/**
* Connect the pulse audio stream
*/
bool connectStream();
bool connectStream(std::string* deviceName);
/**
* Drain the given stream.
......@@ -135,7 +135,7 @@ class AudioStream {
* @param c The pulseaudio context
* @return pa_stream* The newly created audio stream
*/
pa_stream* createStream( pa_context* c);
pa_stream* createStream( pa_context* c, std::string* deviceName);
/**
* Mandatory asynchronous callback on the audio stream state
......
......@@ -133,8 +133,11 @@ static void sink_input_info_callback(pa_context *c, const pa_sink_info *i, int e
i->flags & PA_SINK_LATENCY ? "LATENCY " : "",
i->flags & PA_SINK_HARDWARE ? "HARDWARE" : "");
std::string deviceName(i->name);
((PulseLayer *)userdata)->getDevicelist()->push_back(deviceName);
}
}
......@@ -407,23 +410,59 @@ void PulseLayer::updateDeviceList(void) {
_debug("Audio: Update device list");
getDevicelist()->clear();
pa_context_get_sink_info_list(context, sink_input_info_callback, this);
}
bool PulseLayer::inDevicelist(std::string deviceName) {
_debug("Audio: in device list %s", deviceName.c_str());
DeviceList::iterator iter = _deviceList.begin();
_debug("_deviceList.size() %d", _deviceList.size());
while(iter != _deviceList.end()) {
if (*iter == deviceName) {
_debug("device name in list: %s", (*iter).c_str());
return true;
}
iter++;
}
return false;
}
bool PulseLayer::createStreams (pa_context* c)
{
_info("Audio: Create streams");
// _debug("Device list size %d", getDevicelist()->size());
std::string playbackDevice = _manager->getConfigString(AUDIO, PULSE_DEVICE_PLAYBACK);
std::string recordDevice = _manager->getConfigString(AUDIO, PULSE_DEVICE_PLAYBACK);
std::string ringtoneDevice = _manager->getConfigString(AUDIO, PULSE_DEVICE_PLAYBACK);
_debug("Audio: Device stored in config for playback: %s", playbackDevice.c_str());
_debug("Audio: Device stored in config for ringtone: %s", recordDevice.c_str());
_debug("Audio: Device stored in config for record: %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->connectStream();
playback = new AudioStream(playbackParam, _audioSampleRate);
if(inDevicelist(playbackDevice)) {
playback->connectStream(&playbackDevice);
}
else {
playback->connectStream(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);
......@@ -439,7 +478,12 @@ bool PulseLayer::createStreams (pa_context* c)
recordParam->mainloop = m;
record = new AudioStream (recordParam, _audioSampleRate);
record->connectStream();
if(inDevicelist(recordDevice)) {
record->connectStream(NULL);
}
else {
record->connectStream(NULL);
}
pa_stream_set_read_callback (record->pulseStream() , capture_callback, this);
// pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this);
pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this);
......@@ -453,7 +497,12 @@ bool PulseLayer::createStreams (pa_context* c)
ringtoneParam->mainloop = m;
ringtone = new AudioStream (ringtoneParam, _audioSampleRate);
ringtone->connectStream();
if(inDevicelist(ringtoneDevice)) {
ringtone->connectStream(&ringtoneDevice);
}
else {
ringtone->connectStream(NULL);
}
pa_stream_set_write_callback(ringtone->pulseStream(), ringtone_callback, this);
pa_stream_set_moved_callback(ringtone->pulseStream(), stream_moved_callback, this);
delete ringtoneParam;
......@@ -484,6 +533,10 @@ bool PulseLayer::disconnectAudioStream (void)
void PulseLayer::closeCaptureStream (void)
{
if (record) {
std::string deviceName(pa_stream_get_device_name(record->pulseStream()));
_debug("record device to be stored in config: %s", deviceName.c_str());
_manager->setConfig(AUDIO, PULSE_DEVICE_RECORD, deviceName);
delete record;
record=NULL;
}
......@@ -493,16 +546,20 @@ void PulseLayer::closeCaptureStream (void)
void PulseLayer::closePlaybackStream (void)
{
if (playback) {
std::string deviceName(pa_stream_get_device_name(playback->pulseStream()));
_debug("playback device to be stored in config: %s", deviceName.c_str());
_manager->setConfig(AUDIO, PULSE_DEVICE_PLAYBACK, deviceName);
delete playback;
playback=NULL;
}
if(ringtone) {
std::string deviceName(pa_stream_get_device_name(ringtone->pulseStream()));
_debug("ringtone device to be stored in config: %s", deviceName.c_str());
_manager->setConfig(AUDIO, PULSE_DEVICE_RINGTONE, deviceName);
delete ringtone;
ringtone = NULL;
}
_debug("ringtone is dead");
}
......
......@@ -67,8 +67,12 @@ class PulseLayer : public AudioLayer {
*/
bool openDevice(int indexIn, int indexOut, int sampleRate, int frameSize , int stream, std::string plugin) ;
DeviceList* getDevicelist(void) { return &_deviceList; }
void updateDeviceList(void);
bool inDevicelist(std::string deviceName);
void startStream(void);
void stopStream(void);
......
......@@ -2116,6 +2116,12 @@ void ManagerImpl::initConfigFile (bool load_user_value, std::string alternate) {
_config.addDefaultValue(std::pair<std::string, std::string>(RECORD_PATH,
DFT_RECORD_PATH), AUDIO);
// Pulseaudio stream device
_config.addDefaultValue(std::pair<std::string, std::string>(PULSE_DEVICE_PLAYBACK, ""), AUDIO);
_config.addDefaultValue(std::pair<std::string, std::string>(PULSE_DEVICE_RECORD, ""), AUDIO);
_config.addDefaultValue(std::pair<std::string, std::string>(PULSE_DEVICE_RINGTONE, ""), AUDIO);
// General settings
_config.addDefaultValue(std::pair<std::string, std::string>(ZONE_TONE,
DFT_ZONE), PREFERENCES);
......
......@@ -38,6 +38,9 @@
#define ALSA_FRAME_SIZE "Alsa.framesize" /** Audio layer frame size */
#define ALSA_PLUGIN "Alsa.plugin" /** Alsa plugin */
#define AUDIO_SAMPLE_RATE "Alsa.sampleRate" /** Audio layer sample rate */
#define PULSE_DEVICE_PLAYBACK "Pulse.devicePlayback"
#define PULSE_DEVICE_RECORD "Pulse.deviceRecord"
#define PULSE_DEVICE_RINGTONE "Pulse.deviceRingtone"
#define RING_CHOICE "Rings.ringChoice" /** Ringtone */
#define VOLUME_SPKR "Volume.speakers" /** Speaker volume */
#define VOLUME_MICRO "Volume.micro" /** Mic volume */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment