diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.cpp b/sflphone-common/src/audio/pulseaudio/audiostream.cpp index 91980bbfe82cbe0e1cf1ea82055518d6b3cdd8ae..6a8609747e889016e75e3d960fbd5a5de73d1643 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.cpp +++ b/sflphone-common/src/audio/pulseaudio/audiostream.cpp @@ -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) { diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.h b/sflphone-common/src/audio/pulseaudio/audiostream.h index da8cecec3ced1e157752583322e9e2b3730037e3..14f769d465cd57f73eb36baa95f01a7a7e12150a 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.h +++ b/sflphone-common/src/audio/pulseaudio/audiostream.h @@ -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 diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index a7696ec56ac5ef2ea292ddf7771af66750ed7e74..daf347d371fee2700623644d8589b28d75822e3b 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -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"); } diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h index 8b0d9fa526fea93eaa3d47db6189c2e8632efb7a..0b89f7fb2c5034f76744f59770650b96933acca2 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.h +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h @@ -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); diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index 920db606a43af1d36e35834756ebd4f4305f78de..a552d2ffd62d287645f4c3b9fdf651dfc68b2566 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -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); diff --git a/sflphone-common/src/user_cfg.h b/sflphone-common/src/user_cfg.h index 4e8ce791b81fe8d0d6d221519bc3c35deebeab64..a411b89b139d71e04e11cd067a742e74932c54a8 100644 --- a/sflphone-common/src/user_cfg.h +++ b/sflphone-common/src/user_cfg.h @@ -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 */