67
70
} // end anonymous namespace
70
std::ofstream outfileResampled ("testMicOuputResampled.raw", std::ifstream::binary);
71
std::ofstream outfile("testMicOuput.raw", std::ifstream::binary);
72
PulseMainLoopLock::PulseMainLoopLock(pa_threaded_mainloop *loop) : loop_(loop), destroyLoop_(false)
74
pa_threaded_mainloop_lock(loop_);
77
// set this flag if we want the loop to be destroyed once it's unlocked
78
void PulseMainLoopLock::destroyLoop()
83
PulseMainLoopLock::~PulseMainLoopLock()
85
pa_threaded_mainloop_unlock(loop_);
87
pa_threaded_mainloop_stop(loop_);
88
pa_threaded_mainloop_free(loop_);
74
92
PulseLayer::PulseLayer(AudioPreference &pref)
99
, micBuffer_(0, 1, 8000)
83
101
, mainloop_(pa_threaded_mainloop_new())
84
102
, enumeratingSinks_(false)
85
103
, enumeratingSources_(false)
86
104
, preference_(pref)
88
setenv("PULSE_PROP_media.role", "phone", 1);
106
setCaptureGain(pref.getVolumemic());
107
setPlaybackGain(pref.getVolumespkr());
108
muteCapture(pref.getCaptureMuted());
91
111
throw std::runtime_error("Couldn't create pulseaudio mainloop");
93
context_ = pa_context_new(pa_threaded_mainloop_get_api(mainloop_) , "SFLphone");
113
if (pa_threaded_mainloop_start(mainloop_) < 0) {
114
pa_threaded_mainloop_free(mainloop_);
115
throw std::runtime_error("Failed to start pulseaudio mainloop");
118
PulseMainLoopLock lock(mainloop_);
120
#if PA_CHECK_VERSION(1, 0, 0)
121
pa_proplist *pl = pa_proplist_new();
122
pa_proplist_sets(pl, PA_PROP_MEDIA_ROLE, "phone");
124
context_ = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(mainloop_), "SFLphone", pl);
127
pa_proplist_free(pl);
130
setenv("PULSE_PROP_media.role", "phone", 1);
131
context_ = pa_context_new(pa_threaded_mainloop_get_api(mainloop_), "SFLphone");
96
136
throw std::runtime_error("Couldn't create pulseaudio context");
98
139
pa_context_set_state_callback(context_, context_state_callback, this);
100
if (pa_context_connect(context_, NULL , PA_CONTEXT_NOAUTOSPAWN , NULL) < 0)
141
if (pa_context_connect(context_, nullptr , PA_CONTEXT_NOAUTOSPAWN , nullptr) < 0) {
101
143
throw std::runtime_error("Could not connect pulseaudio context to the server");
103
pa_threaded_mainloop_lock(mainloop_);
105
if (pa_threaded_mainloop_start(mainloop_) < 0)
106
throw std::runtime_error("Failed to start pulseaudio mainloop");
108
pa_threaded_mainloop_wait(mainloop_);
110
if (pa_context_get_state(context_) != PA_CONTEXT_READY)
111
throw std::runtime_error("Couldn't connect to pulse audio server");
113
pa_threaded_mainloop_unlock(mainloop_);
146
// wait until context is ready
148
pa_context_state_t context_state = pa_context_get_state(context_);
149
if (not PA_CONTEXT_IS_GOOD(context_state)) {
151
throw std::runtime_error("Pulse audio context is bad");
153
if (context_state == PA_CONTEXT_READY)
155
pa_threaded_mainloop_wait(mainloop_);
115
158
isStarted_ = true;
118
161
PulseLayer::~PulseLayer()
122
outfileResampled.close();
125
163
disconnectAudioStream();
128
pa_threaded_mainloop_stop(mainloop_);
166
PulseMainLoopLock lock(mainloop_);
168
pa_context_set_state_callback(context_, NULL, NULL);
131
169
pa_context_disconnect(context_);
132
170
pa_context_unref(context_);
136
pa_threaded_mainloop_free(mainloop_);
138
delete [] mic_buffer_;
173
pa_threaded_mainloop_stop(mainloop_);
174
pa_threaded_mainloop_free(mainloop_);
141
177
void PulseLayer::context_state_callback(pa_context* c, void *user_data)
188
224
sourceList_.clear();
189
225
enumeratingSources_ = true;
190
226
pa_operation *op = pa_context_get_source_info_list(context_, source_input_info_callback, this);
192
229
pa_operation_unref(op);
195
bool PulseLayer::inSinkList(const std::string &deviceName) const
232
bool PulseLayer::inSinkList(const std::string &deviceName)
197
const bool found = std::find(sinkList_.begin(), sinkList_.end(), deviceName) != sinkList_.end();
234
const bool found = std::find_if(sinkList_.begin(), sinkList_.end(), PaDeviceInfos::nameComparator(deviceName)) != sinkList_.end();
198
236
DEBUG("seeking for %s in sinks. %s found", deviceName.c_str(), found ? "" : "NOT");
203
bool PulseLayer::inSourceList(const std::string &deviceName) const
240
bool PulseLayer::inSourceList(const std::string &deviceName)
205
const bool found = std::find(sourceList_.begin(), sourceList_.end(), deviceName) != sourceList_.end();
242
const bool found = std::find_if(sourceList_.begin(), sourceList_.end(), PaDeviceInfos::nameComparator(deviceName)) != sourceList_.end();
206
244
DEBUG("seeking for %s in sources. %s found", deviceName.c_str(), found ? "" : "NOT");
210
248
std::vector<std::string> PulseLayer::getCaptureDeviceList() const
250
const unsigned n = sourceList_.size();
251
std::vector<std::string> names(n);
253
for (unsigned i = 0; i < n; i++)
254
names[i] = sourceList_[i].name;
215
259
std::vector<std::string> PulseLayer::getPlaybackDeviceList() const
261
const unsigned n = sinkList_.size();
262
std::vector<std::string> names(n);
264
for (unsigned i = 0; i < n; i++)
265
names[i] = sinkList_[i].name;
220
270
int PulseLayer::getAudioDeviceIndex(const std::string& name) const
222
int index = std::distance(sourceList_.begin(), std::find(sourceList_.begin(), sourceList_.end(), name));
272
int index = std::distance(sourceList_.begin(), std::find_if(sourceList_.begin(), sourceList_.end(), PaDeviceInfos::nameComparator(name)));
223
274
if (index == std::distance(sourceList_.begin(), sourceList_.end())) {
224
// not found in sources, search in sinks then
225
index = std::distance(sinkList_.begin(), std::find(sinkList_.begin(), sinkList_.end(), name));
275
index = std::distance(sinkList_.begin(), std::find_if(sinkList_.begin(), sinkList_.end(), PaDeviceInfos::nameComparator(name)));
281
const PaDeviceInfos* PulseLayer::getDeviceInfos(const std::vector<PaDeviceInfos>& list, const std::string& name) const
283
std::vector<PaDeviceInfos>::const_iterator dev_info = std::find_if(list.begin(), list.end(), PaDeviceInfos::nameComparator(name));
285
if (dev_info == list.end()) return nullptr;
230
290
std::string PulseLayer::getAudioDeviceName(int index, PCMType type) const
233
294
case SFL_PCM_PLAYBACK:
234
295
case SFL_PCM_RINGTONE:
258
323
std::string ringtoneDevice(preference_.getPulseDeviceRingtone());
259
324
std::string defaultDevice = "";
261
DEBUG("Devices:\n playback: %s\n record: %s\n ringtone: %s",
262
playbackDevice.c_str(), captureDevice.c_str(), ringtoneDevice.c_str());
264
playback_ = new AudioStream(c, mainloop_, "SFLphone playback", PLAYBACK_STREAM, sampleRate_,
265
inSinkList(playbackDevice) ? playbackDevice : defaultDevice);
326
DEBUG("Devices: playback: %s record: %s ringtone: %s",
327
playbackDevice.c_str(), captureDevice.c_str(), ringtoneDevice.c_str());
329
// Create playback stream
330
const PaDeviceInfos* dev_infos = getDeviceInfos(sinkList_, playbackDevice);
332
if (dev_infos == nullptr) {
333
dev_infos = &sinkList_[0];
334
DEBUG("Prefered playback device not found in device list, selecting %s instead.", dev_infos->name.c_str());
337
playback_ = new AudioStream(c, mainloop_, "SFLphone playback", PLAYBACK_STREAM, sampleRate_, dev_infos);
267
339
pa_stream_set_write_callback(playback_->pulseStream(), playback_callback, this);
268
340
pa_stream_set_moved_callback(playback_->pulseStream(), stream_moved_callback, this);
270
record_ = new AudioStream(c, mainloop_, "SFLphone capture", CAPTURE_STREAM, sampleRate_,
271
inSourceList(captureDevice) ? captureDevice : defaultDevice);
342
// Create capture stream
343
dev_infos = getDeviceInfos(sourceList_, captureDevice);
345
if (dev_infos == nullptr) {
346
dev_infos = &sourceList_[0];
347
DEBUG("Prefered capture device not found in device list, selecting %s instead.", dev_infos->name.c_str());
350
record_ = new AudioStream(c, mainloop_, "SFLphone capture", CAPTURE_STREAM, sampleRate_, dev_infos);
273
352
pa_stream_set_read_callback(record_->pulseStream() , capture_callback, this);
274
353
pa_stream_set_moved_callback(record_->pulseStream(), stream_moved_callback, this);
276
ringtone_ = new AudioStream(c, mainloop_, "SFLphone ringtone", RINGTONE_STREAM, sampleRate_,
277
inSinkList(ringtoneDevice) ? ringtoneDevice : defaultDevice);
355
// Create ringtone stream
356
dev_infos = getDeviceInfos(sinkList_, ringtoneDevice);
358
if (dev_infos == nullptr) {
359
dev_infos = &sinkList_[0];
360
DEBUG("Prefered ringtone device not found in device list, selecting %s instead.", dev_infos->name.c_str());
363
ringtone_ = new AudioStream(c, mainloop_, "SFLphone ringtone", RINGTONE_STREAM, sampleRate_, dev_infos);
279
365
pa_stream_set_write_callback(ringtone_->pulseStream(), ringtone_callback, this);
280
366
pa_stream_set_moved_callback(ringtone_->pulseStream(), stream_moved_callback, this);
351
440
size_t writableBytes = ret;
441
const size_t writableSamples = writableBytes / sample_size;
353
443
notifyIncomingCall();
355
size_t urgentBytes = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);
357
if (urgentBytes > writableBytes)
358
urgentBytes = writableBytes;
445
size_t urgentSamples = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);
446
size_t urgentBytes = urgentSamples * sample_size;
448
if (urgentSamples > writableSamples) {
449
urgentSamples = writableSamples;
450
urgentBytes = urgentSamples * sample_size;
453
SFLAudioSample *data = 0;
361
455
if (urgentBytes) {
362
pa_stream_begin_write(s, &data, &urgentBytes);
363
urgentRingBuffer_.get(data, urgentBytes, MainBuffer::DEFAULT_ID);
364
applyGain(static_cast<SFLDataFormat *>(data), urgentBytes / sizeof(SFLDataFormat), getPlaybackGain());
365
pa_stream_write(s, data, urgentBytes, NULL, 0, PA_SEEK_RELATIVE);
366
// Consume the regular one as well (same amount of bytes)
367
Manager::instance().getMainBuffer().discard(urgentBytes, MainBuffer::DEFAULT_ID);
456
AudioBuffer linearbuff(urgentSamples, n_channels, 8000);
457
pa_stream_begin_write(s, (void**)&data, &urgentBytes);
458
urgentRingBuffer_.get(linearbuff, MainBuffer::DEFAULT_ID); // retrive only the first sample_spec->channels channels
459
linearbuff.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
460
linearbuff.interleave(data);
461
pa_stream_write(s, data, urgentBytes, nullptr, 0, PA_SEEK_RELATIVE);
462
// Consume the regular one as well (same amount of samples)
463
Manager::instance().getMainBuffer().discard(urgentSamples, MainBuffer::DEFAULT_ID);
375
471
if (toneToPlay) {
376
472
if (playback_->isReady()) {
377
pa_stream_begin_write(s, &data, &writableBytes);
378
toneToPlay->getNext((SFLDataFormat*)data, writableBytes / sizeof(SFLDataFormat), 100);
379
applyGain(static_cast<SFLDataFormat *>(data), writableBytes / sizeof(SFLDataFormat), getPlaybackGain());
380
pa_stream_write(s, data, writableBytes, NULL, 0, PA_SEEK_RELATIVE);
473
pa_stream_begin_write(s, (void**)&data, &writableBytes);
474
AudioBuffer linearbuff(writableSamples, n_channels, 8000);
475
toneToPlay->getNext(linearbuff, playbackGain_); // retrive only n_channels
476
linearbuff.interleave(data);
477
pa_stream_write(s, data, writableBytes, nullptr, 0, PA_SEEK_RELATIVE);
386
483
flushUrgent(); // flush remaining samples in _urgentRingBuffer
388
size_t availSamples = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID) / sizeof(SFLDataFormat);
485
size_t availSamples = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID);
390
487
if (availSamples == 0) {
391
pa_stream_begin_write(s, &data, &writableBytes);
488
pa_stream_begin_write(s, (void**)&data, &writableBytes);
392
489
memset(data, 0, writableBytes);
393
pa_stream_write(s, data, writableBytes, NULL, 0, PA_SEEK_RELATIVE);
490
pa_stream_write(s, data, writableBytes, nullptr, 0, PA_SEEK_RELATIVE);
397
// how many samples we can write to the output
398
size_t writableSamples = writableBytes / sizeof(SFLDataFormat);
400
494
// how many samples we want to read from the buffer
401
495
size_t readableSamples = writableSamples;
405
499
unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
406
500
bool resample = sampleRate_ != mainBufferSampleRate;
408
503
resampleFactor = (double) sampleRate_ / mainBufferSampleRate;
409
504
readableSamples = (double) readableSamples / resampleFactor;
412
if (readableSamples > availSamples)
413
readableSamples = availSamples;
415
size_t readableBytes = readableSamples * sizeof(SFLDataFormat);
416
pa_stream_begin_write(s, &data, &readableBytes);
417
Manager::instance().getMainBuffer().getData(data, readableBytes, MainBuffer::DEFAULT_ID);
507
readableSamples = std::min(readableSamples, availSamples);
508
size_t nResampled = (double) readableSamples * resampleFactor;
509
size_t resampledBytes = nResampled * sample_size;
511
pa_stream_begin_write(s, (void**)&data, &resampledBytes);
513
AudioBuffer linearbuff(readableSamples, n_channels, 8000);
514
Manager::instance().getMainBuffer().getData(linearbuff, MainBuffer::DEFAULT_ID);
420
const size_t nResampled = (double) readableSamples * resampleFactor;
421
size_t resampledBytes = nResampled * sizeof(SFLDataFormat);
422
SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc(resampledBytes);
423
converter_.resample((SFLDataFormat*)data, rsmpl_out, nResampled,
424
mainBufferSampleRate, sampleRate_, readableSamples);
425
applyGain(rsmpl_out, nResampled, getPlaybackGain());
426
pa_stream_write(s, rsmpl_out, resampledBytes, NULL, 0, PA_SEEK_RELATIVE);
517
AudioBuffer rsmpl_out(nResampled, 1, sampleRate_);
518
converter_.resample(linearbuff, rsmpl_out);
519
rsmpl_out.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
520
rsmpl_out.interleave(data);
521
pa_stream_write(s, data, resampledBytes, nullptr, 0, PA_SEEK_RELATIVE);
429
applyGain(static_cast<SFLDataFormat *>(data), readableSamples, getPlaybackGain());
430
pa_stream_write(s, data, readableBytes, NULL, 0, PA_SEEK_RELATIVE);
523
linearbuff.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
524
linearbuff.interleave(data);
525
pa_stream_write(s, data, resampledBytes, nullptr, 0, PA_SEEK_RELATIVE);
436
531
if (!record_ or !record_->isReady())
439
const char *data = NULL;
534
const char *data = nullptr;
537
const size_t sample_size = record_->sampleSize();
538
const uint8_t channels = record_->channels();
442
540
if (pa_stream_peek(record_->pulseStream() , (const void**) &data , &bytes) < 0 or !data)
545
const size_t samples = bytes / sample_size / channels;
547
AudioBuffer in(samples, channels, sampleRate_);
548
in.deinterleave((SFLAudioSample*)data, samples, channels);
445
550
unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
446
551
bool resample = sampleRate_ != mainBufferSampleRate;
449
double resampleFactor = (double) sampleRate_ / mainBufferSampleRate;
450
bytes = (double) bytes * resampleFactor;
453
size_t samples = bytes / sizeof(SFLDataFormat);
455
if (bytes > mic_buf_size_) {
456
mic_buf_size_ = bytes;
457
delete [] mic_buffer_;
458
mic_buffer_ = new SFLDataFormat[samples];
462
outfile.write((const char *)data, bytes);
465
converter_.resample((SFLDataFormat*)data, mic_buffer_, samples, mainBufferSampleRate, sampleRate_, samples);
468
dcblocker_.process(mic_buffer_, (SFLDataFormat*)data, samples);
469
applyGain(mic_buffer_, bytes / sizeof(SFLDataFormat), getCaptureGain());
470
Manager::instance().getMainBuffer().putData(mic_buffer_, bytes, MainBuffer::DEFAULT_ID);
472
outfileResampled.write((const char *)mic_buffer_, bytes);
553
in.applyGain(isCaptureMuted_ ? 0.0 : captureGain_);
555
AudioBuffer * out = ∈
558
micBuffer_.setSampleRate(mainBufferSampleRate);
559
converter_.resample(in, micBuffer_);
563
dcblocker_.process(*out);
564
out->applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
565
Manager::instance().getMainBuffer().putData(*out, MainBuffer::DEFAULT_ID);
475
567
if (pa_stream_drop(record_->pulseStream()) < 0)
476
568
ERROR("Capture stream drop failed: %s" , pa_strerror(pa_context_errno(context_)));
499
592
AudioLoop *fileToPlay = Manager::instance().getTelephoneFile();
501
594
if (fileToPlay) {
502
fileToPlay->getNext((SFLDataFormat *) data, bytes / sizeof(SFLDataFormat), 100);
503
applyGain(static_cast<SFLDataFormat *>(data), bytes / sizeof(SFLDataFormat), getPlaybackGain());
595
const unsigned samples = (bytes / sample_size) / ringtone_->channels();
596
AudioBuffer tmp(samples, ringtone_->channels(), 8000);
597
fileToPlay->getNext(tmp, playbackGain_);
598
tmp.interleave((SFLAudioSample*) data);
506
600
memset(data, 0, bytes);
508
pa_stream_write(s, data, bytes, NULL, 0, PA_SEEK_RELATIVE);
603
pa_stream_write(s, data, bytes, nullptr, 0, PA_SEEK_RELATIVE);
564
667
DEBUG("Source %u\n"
568
" Sample Specification: %s\n"
570
" Owner Module: %u\n"
572
" Monitor if Sink: %u\n"
573
" Latency: %0.0f usec\n"
579
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
580
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
582
i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
585
i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
586
i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
587
i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : "");
671
" Sample Specification: %s\n"
673
" Owner Module: %u\n"
675
" Monitor if Sink: %u\n"
676
" Latency: %0.0f usec\n"
682
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
683
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
685
i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
688
i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
689
i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
690
i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : "");
589
if (not context->inSourceList(i->name))
590
context->sourceList_.push_back(i->name);
692
if (not context->inSourceList(i->name)) {
693
PaDeviceInfos ep_infos(i->index, i->name, i->sample_spec, i->channel_map);
694
context->sourceList_.push_back(ep_infos);
593
698
void PulseLayer::sink_input_info_callback(pa_context *c UNUSED, const pa_sink_info *i, int eol, void *userdata)
625
730
i->flags & PA_SINK_LATENCY ? "LATENCY " : "",
626
731
i->flags & PA_SINK_HARDWARE ? "HARDWARE" : "");
628
if (not context->inSinkList(i->name))
629
context->sinkList_.push_back(i->name);
733
if (not context->inSinkList(i->name)) {
734
PaDeviceInfos ep_infos(i->index, i->name, i->sample_spec, i->channel_map);
735
context->sinkList_.push_back(ep_infos);
632
739
void PulseLayer::updatePreference(AudioPreference &preference, int index, PCMType type)
634
741
const std::string devName(getAudioDeviceName(index, type));
636
744
case SFL_PCM_PLAYBACK:
637
745
DEBUG("setting %s for playback", devName.c_str());
638
746
preference.setPulseDevicePlayback(devName);
640
749
case SFL_PCM_CAPTURE:
641
750
DEBUG("setting %s for capture", devName.c_str());
642
751
preference.setPulseDeviceRecord(devName);
644
754
case SFL_PCM_RINGTONE:
645
755
DEBUG("setting %s for ringer", devName.c_str());
646
756
preference.setPulseDeviceRingtone(devName);