~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/src/audio/pulseaudio/pulselayer.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
 
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
3
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
4
4
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
5
5
 *  Author: Андрей Лухнов <aol.nnov@gmail.com>
 
6
 *  Author: Adrien Beraud <adrien.beraud@gmail.com>
6
7
 *
7
8
 *  This program is free software; you can redistribute it and/or modify
8
9
 *  it under the terms of the GNU General Public License as published by
32
33
 
33
34
#include <algorithm> // for std::find
34
35
#include <stdexcept>
 
36
 
35
37
#include "audiostream.h"
36
38
#include "pulselayer.h"
37
39
#include "audio/samplerateconverter.h"
39
41
#include "logger.h"
40
42
#include "manager.h"
41
43
 
 
44
#include <unistd.h>
42
45
#include <cstdlib>
43
46
#include <fstream>
44
47
 
66
69
 
67
70
} // end anonymous namespace
68
71
 
69
 
#ifdef RECTODISK
70
 
std::ofstream outfileResampled ("testMicOuputResampled.raw", std::ifstream::binary);
71
 
std::ofstream outfile("testMicOuput.raw", std::ifstream::binary);
72
 
#endif
 
72
PulseMainLoopLock::PulseMainLoopLock(pa_threaded_mainloop *loop) : loop_(loop), destroyLoop_(false)
 
73
{
 
74
    pa_threaded_mainloop_lock(loop_);
 
75
}
 
76
 
 
77
// set this flag if we want the loop to be destroyed once it's unlocked
 
78
void PulseMainLoopLock::destroyLoop()
 
79
{
 
80
    destroyLoop_ = true;
 
81
}
 
82
 
 
83
PulseMainLoopLock::~PulseMainLoopLock()
 
84
{
 
85
    pa_threaded_mainloop_unlock(loop_);
 
86
    if (destroyLoop_) {
 
87
        pa_threaded_mainloop_stop(loop_);
 
88
        pa_threaded_mainloop_free(loop_);
 
89
    }
 
90
}
73
91
 
74
92
PulseLayer::PulseLayer(AudioPreference &pref)
75
 
    : playback_(0)
 
93
    : AudioLayer(pref)
 
94
    , playback_(0)
76
95
    , record_(0)
77
96
    , ringtone_(0)
78
97
    , sinkList_()
79
98
    , sourceList_()
80
 
    , mic_buffer_(0)
81
 
    , mic_buf_size_(0)
 
99
    , micBuffer_(0, 1, 8000)
82
100
    , context_(0)
83
101
    , mainloop_(pa_threaded_mainloop_new())
84
102
    , enumeratingSinks_(false)
85
103
    , enumeratingSources_(false)
86
104
    , preference_(pref)
87
105
{
88
 
    setenv("PULSE_PROP_media.role", "phone", 1);
 
106
    setCaptureGain(pref.getVolumemic());
 
107
    setPlaybackGain(pref.getVolumespkr());
 
108
    muteCapture(pref.getCaptureMuted());
89
109
 
90
110
    if (!mainloop_)
91
111
        throw std::runtime_error("Couldn't create pulseaudio mainloop");
92
112
 
93
 
    context_ = pa_context_new(pa_threaded_mainloop_get_api(mainloop_) , "SFLphone");
94
 
 
95
 
    if (!context_)
 
113
    if (pa_threaded_mainloop_start(mainloop_) < 0) {
 
114
        pa_threaded_mainloop_free(mainloop_);
 
115
        throw std::runtime_error("Failed to start pulseaudio mainloop");
 
116
    }
 
117
 
 
118
    PulseMainLoopLock lock(mainloop_);
 
119
 
 
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");
 
123
 
 
124
    context_ = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(mainloop_), "SFLphone", pl);
 
125
 
 
126
    if (pl)
 
127
        pa_proplist_free(pl);
 
128
 
 
129
#else
 
130
    setenv("PULSE_PROP_media.role", "phone", 1);
 
131
    context_ = pa_context_new(pa_threaded_mainloop_get_api(mainloop_), "SFLphone");
 
132
#endif
 
133
 
 
134
    if (!context_) {
 
135
        lock.destroyLoop();
96
136
        throw std::runtime_error("Couldn't create pulseaudio context");
 
137
    }
97
138
 
98
139
    pa_context_set_state_callback(context_, context_state_callback, this);
99
140
 
100
 
    if (pa_context_connect(context_, NULL , PA_CONTEXT_NOAUTOSPAWN , NULL) < 0)
 
141
    if (pa_context_connect(context_, nullptr , PA_CONTEXT_NOAUTOSPAWN , nullptr) < 0) {
 
142
        lock.destroyLoop();
101
143
        throw std::runtime_error("Could not connect pulseaudio context to the server");
102
 
 
103
 
    pa_threaded_mainloop_lock(mainloop_);
104
 
 
105
 
    if (pa_threaded_mainloop_start(mainloop_) < 0)
106
 
        throw std::runtime_error("Failed to start pulseaudio mainloop");
107
 
 
108
 
    pa_threaded_mainloop_wait(mainloop_);
109
 
 
110
 
    if (pa_context_get_state(context_) != PA_CONTEXT_READY)
111
 
        throw std::runtime_error("Couldn't connect to pulse audio server");
112
 
 
113
 
    pa_threaded_mainloop_unlock(mainloop_);
 
144
    }
 
145
 
 
146
    // wait until context is ready
 
147
    for (;;) {
 
148
        pa_context_state_t context_state = pa_context_get_state(context_);
 
149
        if (not PA_CONTEXT_IS_GOOD(context_state)) {
 
150
            lock.destroyLoop();
 
151
            throw std::runtime_error("Pulse audio context is bad");
 
152
        }
 
153
        if (context_state == PA_CONTEXT_READY)
 
154
            break;
 
155
        pa_threaded_mainloop_wait(mainloop_);
 
156
    }
114
157
 
115
158
    isStarted_ = true;
116
159
}
117
160
 
118
161
PulseLayer::~PulseLayer()
119
162
{
120
 
#ifdef RECTODISK
121
 
    outfile.close();
122
 
    outfileResampled.close();
123
 
#endif
124
 
 
125
163
    disconnectAudioStream();
126
164
 
127
 
    if (mainloop_)
128
 
        pa_threaded_mainloop_stop(mainloop_);
 
165
    {
 
166
        PulseMainLoopLock lock(mainloop_);
129
167
 
130
 
    if (context_) {
 
168
        pa_context_set_state_callback(context_, NULL, NULL);
131
169
        pa_context_disconnect(context_);
132
170
        pa_context_unref(context_);
133
171
    }
134
172
 
135
 
    if (mainloop_)
136
 
        pa_threaded_mainloop_free(mainloop_);
137
 
 
138
 
    delete [] mic_buffer_;
 
173
    pa_threaded_mainloop_stop(mainloop_);
 
174
    pa_threaded_mainloop_free(mainloop_);
139
175
}
140
176
 
141
177
void PulseLayer::context_state_callback(pa_context* c, void *user_data)
143
179
    PulseLayer *pulse = static_cast<PulseLayer*>(user_data);
144
180
    assert(c and pulse and pulse->mainloop_);
145
181
    const pa_subscription_mask_t mask = (pa_subscription_mask_t)
146
 
        (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE);
 
182
                                        (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE);
147
183
 
148
184
    switch (pa_context_get_state(c)) {
149
185
        case PA_CONTEXT_CONNECTING:
155
191
        case PA_CONTEXT_READY:
156
192
            DEBUG("Connection to PulseAudio server established");
157
193
            pa_threaded_mainloop_signal(pulse->mainloop_, 0);
158
 
            pa_context_subscribe(c, mask, NULL, pulse);
 
194
            pa_context_subscribe(c, mask, nullptr, pulse);
159
195
            pa_context_set_subscribe_callback(c, context_changed_callback, pulse);
160
196
            pulse->updateSinkList();
161
197
            pulse->updateSourceList();
168
204
        default:
169
205
            ERROR("%s" , pa_strerror(pa_context_errno(c)));
170
206
            pa_threaded_mainloop_signal(pulse->mainloop_, 0);
171
 
            pulse->disconnectAudioStream();
172
207
            break;
173
208
    }
174
209
}
179
214
    sinkList_.clear();
180
215
    enumeratingSinks_ = true;
181
216
    pa_operation *op = pa_context_get_sink_info_list(context_, sink_input_info_callback, this);
182
 
    if (op != NULL)
 
217
 
 
218
    if (op != nullptr)
183
219
        pa_operation_unref(op);
184
220
}
185
221
 
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);
191
 
    if (op != NULL)
 
227
 
 
228
    if (op != nullptr)
192
229
        pa_operation_unref(op);
193
230
}
194
231
 
195
 
bool PulseLayer::inSinkList(const std::string &deviceName) const
 
232
bool PulseLayer::inSinkList(const std::string &deviceName)
196
233
{
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();
 
235
 
198
236
    DEBUG("seeking for %s in sinks. %s found", deviceName.c_str(), found ? "" : "NOT");
199
237
    return found;
200
238
}
201
239
 
202
 
 
203
 
bool PulseLayer::inSourceList(const std::string &deviceName) const
 
240
bool PulseLayer::inSourceList(const std::string &deviceName)
204
241
{
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();
 
243
 
206
244
    DEBUG("seeking for %s in sources. %s found", deviceName.c_str(), found ? "" : "NOT");
207
245
    return found;
208
246
}
209
247
 
210
248
std::vector<std::string> PulseLayer::getCaptureDeviceList() const
211
249
{
212
 
    return sourceList_;
 
250
    const unsigned n = sourceList_.size();
 
251
    std::vector<std::string> names(n);
 
252
 
 
253
    for (unsigned i = 0; i < n; i++)
 
254
        names[i] = sourceList_[i].name;
 
255
 
 
256
    return names;
213
257
}
214
258
 
215
259
std::vector<std::string> PulseLayer::getPlaybackDeviceList() const
216
260
{
217
 
    return sinkList_;
 
261
    const unsigned n = sinkList_.size();
 
262
    std::vector<std::string> names(n);
 
263
 
 
264
    for (unsigned i = 0; i < n; i++)
 
265
        names[i] = sinkList_[i].name;
 
266
 
 
267
    return names;
218
268
}
219
269
 
220
270
int PulseLayer::getAudioDeviceIndex(const std::string& name) const
221
271
{
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)));
 
273
 
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)));
226
276
    }
 
277
 
227
278
    return index;
228
279
}
229
280
 
 
281
const PaDeviceInfos* PulseLayer::getDeviceInfos(const std::vector<PaDeviceInfos>& list, const std::string& name) const
 
282
{
 
283
    std::vector<PaDeviceInfos>::const_iterator dev_info = std::find_if(list.begin(), list.end(), PaDeviceInfos::nameComparator(name));
 
284
 
 
285
    if (dev_info == list.end()) return nullptr;
 
286
 
 
287
    return &(*dev_info);
 
288
}
 
289
 
230
290
std::string PulseLayer::getAudioDeviceName(int index, PCMType type) const
231
291
{
 
292
 
232
293
    switch (type) {
233
294
        case SFL_PCM_PLAYBACK:
234
295
        case SFL_PCM_RINGTONE:
236
297
                ERROR("Index %d out of range", index);
237
298
                return "";
238
299
            }
239
 
            return sinkList_[index];
 
300
 
 
301
            return sinkList_[index].name;
 
302
 
240
303
        case SFL_PCM_CAPTURE:
241
304
            if (index < 0 or static_cast<size_t>(index) >= sourceList_.size()) {
242
305
                ERROR("Index %d out of range", index);
243
306
                return "";
244
307
            }
245
 
            return sourceList_[index];
 
308
 
 
309
            return sourceList_[index].name;
 
310
 
246
311
        default:
247
312
            return "";
248
313
    }
258
323
    std::string ringtoneDevice(preference_.getPulseDeviceRingtone());
259
324
    std::string defaultDevice = "";
260
325
 
261
 
    DEBUG("Devices:\n   playback: %s\n   record: %s\n   ringtone: %s",
262
 
           playbackDevice.c_str(), captureDevice.c_str(), ringtoneDevice.c_str());
263
 
 
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());
 
328
 
 
329
    // Create playback stream
 
330
    const PaDeviceInfos* dev_infos = getDeviceInfos(sinkList_, playbackDevice);
 
331
 
 
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());
 
335
    }
 
336
 
 
337
    playback_ = new AudioStream(c, mainloop_, "SFLphone playback", PLAYBACK_STREAM, sampleRate_, dev_infos);
266
338
 
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);
269
341
 
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);
 
344
 
 
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());
 
348
    }
 
349
 
 
350
    record_ = new AudioStream(c, mainloop_, "SFLphone capture", CAPTURE_STREAM, sampleRate_, dev_infos);
272
351
 
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);
275
354
 
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);
 
357
 
 
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());
 
361
    }
 
362
 
 
363
    ringtone_ = new AudioStream(c, mainloop_, "SFLphone ringtone", RINGTONE_STREAM, sampleRate_, dev_infos);
278
364
 
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);
286
372
}
287
373
 
288
374
namespace {
289
 
    // Delete stream and zero out its pointer
290
 
    void
291
 
    cleanupStream(AudioStream *&stream)
292
 
    {
293
 
        delete stream;
294
 
        stream = 0;
295
 
    }
 
375
// Delete stream and zero out its pointer
 
376
void
 
377
cleanupStream(AudioStream *&stream)
 
378
{
 
379
    delete stream;
 
380
    stream = 0;
 
381
}
296
382
}
297
383
 
298
384
 
319
405
void
320
406
PulseLayer::stopStream()
321
407
{
322
 
    pa_threaded_mainloop_lock(mainloop_);
323
 
 
324
 
    if (playback_)
325
 
        pa_stream_flush(playback_->pulseStream(), NULL, NULL);
326
 
 
327
 
    if (record_)
328
 
        pa_stream_flush(record_->pulseStream(), NULL, NULL);
329
 
 
330
 
    pa_threaded_mainloop_unlock(mainloop_);
 
408
    {
 
409
        PulseMainLoopLock lock(mainloop_);
 
410
 
 
411
        if (playback_)
 
412
            pa_stream_flush(playback_->pulseStream(), nullptr, nullptr);
 
413
 
 
414
        if (record_)
 
415
            pa_stream_flush(record_->pulseStream(), nullptr, nullptr);
 
416
    }
331
417
 
332
418
    disconnectAudioStream();
333
419
}
338
424
        return;
339
425
 
340
426
    pa_stream *s = playback_->pulseStream();
 
427
    const pa_sample_spec* sample_spec = pa_stream_get_sample_spec(s);
 
428
    size_t sample_size = pa_frame_size(sample_spec);
 
429
    const unsigned n_channels = sample_spec->channels;
341
430
 
342
431
    // available bytes to be written in pulseaudio internal buffer
343
432
    int ret = pa_stream_writable_size(s);
349
438
        return;
350
439
 
351
440
    size_t writableBytes = ret;
 
441
    const size_t writableSamples = writableBytes / sample_size;
352
442
 
353
443
    notifyIncomingCall();
354
444
 
355
 
    size_t urgentBytes = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);
356
 
 
357
 
    if (urgentBytes > writableBytes)
358
 
        urgentBytes = writableBytes;
359
 
 
360
 
    void *data = 0;
 
445
    size_t urgentSamples = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);
 
446
    size_t urgentBytes = urgentSamples * sample_size;
 
447
 
 
448
    if (urgentSamples > writableSamples) {
 
449
        urgentSamples = writableSamples;
 
450
        urgentBytes = urgentSamples * sample_size;
 
451
    }
 
452
 
 
453
    SFLAudioSample *data = 0;
 
454
 
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);
368
464
        return;
369
465
    }
370
466
 
374
470
 
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);
381
478
        }
382
479
 
383
480
        return;
385
482
 
386
483
    flushUrgent(); // flush remaining samples in _urgentRingBuffer
387
484
 
388
 
    size_t availSamples = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID) / sizeof(SFLDataFormat);
 
485
    size_t availSamples = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID);
389
486
 
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);
394
491
        return;
395
492
    }
396
493
 
397
 
    // how many samples we can write to the output
398
 
    size_t writableSamples = writableBytes / sizeof(SFLDataFormat);
399
 
 
400
494
    // how many samples we want to read from the buffer
401
495
    size_t readableSamples = writableSamples;
402
496
 
404
498
 
405
499
    unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
406
500
    bool resample = sampleRate_ != mainBufferSampleRate;
 
501
 
407
502
    if (resample) {
408
503
        resampleFactor = (double) sampleRate_ / mainBufferSampleRate;
409
504
        readableSamples = (double) readableSamples / resampleFactor;
410
505
    }
411
506
 
412
 
    if (readableSamples > availSamples)
413
 
        readableSamples = availSamples;
414
 
 
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;
 
510
 
 
511
    pa_stream_begin_write(s, (void**)&data, &resampledBytes);
 
512
 
 
513
    AudioBuffer linearbuff(readableSamples, n_channels, 8000);
 
514
    Manager::instance().getMainBuffer().getData(linearbuff, MainBuffer::DEFAULT_ID);
418
515
 
419
516
    if (resample) {
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);
427
 
        pa_xfree(rsmpl_out);
 
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);
428
522
    } else {
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);
431
526
    }
432
527
}
433
528
 
436
531
    if (!record_ or !record_->isReady())
437
532
        return;
438
533
 
439
 
    const char *data = NULL;
 
534
    const char *data = nullptr;
440
535
    size_t bytes;
441
536
 
 
537
    const size_t sample_size = record_->sampleSize();
 
538
    const uint8_t channels = record_->channels();
 
539
 
442
540
    if (pa_stream_peek(record_->pulseStream() , (const void**) &data , &bytes) < 0 or !data)
443
541
        return;
444
542
 
 
543
    assert(channels);
 
544
    assert(sample_size);
 
545
    const size_t samples = bytes / sample_size / channels;
 
546
 
 
547
    AudioBuffer in(samples, channels, sampleRate_);
 
548
    in.deinterleave((SFLAudioSample*)data, samples, channels);
 
549
 
445
550
    unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer().getInternalSamplingRate();
446
551
    bool resample = sampleRate_ != mainBufferSampleRate;
447
552
 
448
 
    if (resample) {
449
 
        double resampleFactor = (double) sampleRate_ / mainBufferSampleRate;
450
 
        bytes = (double) bytes * resampleFactor;
451
 
    }
452
 
 
453
 
    size_t samples = bytes / sizeof(SFLDataFormat);
454
 
 
455
 
    if (bytes > mic_buf_size_) {
456
 
        mic_buf_size_ = bytes;
457
 
        delete [] mic_buffer_;
458
 
        mic_buffer_ = new SFLDataFormat[samples];
459
 
    }
460
 
 
461
 
#ifdef RECTODISK
462
 
    outfile.write((const char *)data, bytes);
463
 
#endif
464
 
    if (resample) {
465
 
        converter_.resample((SFLDataFormat*)data, mic_buffer_, samples, mainBufferSampleRate, sampleRate_, samples);
466
 
    }
467
 
 
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);
471
 
#ifdef RECTODISK
472
 
    outfileResampled.write((const char *)mic_buffer_, bytes);
473
 
#endif
 
553
    in.applyGain(isCaptureMuted_ ? 0.0 : captureGain_);
 
554
 
 
555
    AudioBuffer * out = &in;
 
556
 
 
557
    if (resample) {
 
558
        micBuffer_.setSampleRate(mainBufferSampleRate);
 
559
        converter_.resample(in, micBuffer_);
 
560
        out = &micBuffer_;
 
561
    }
 
562
 
 
563
    dcblocker_.process(*out);
 
564
    out->applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
 
565
    Manager::instance().getMainBuffer().putData(*out, MainBuffer::DEFAULT_ID);
474
566
 
475
567
    if (pa_stream_drop(record_->pulseStream()) < 0)
476
568
        ERROR("Capture stream drop failed: %s" , pa_strerror(pa_context_errno(context_)));
483
575
        return;
484
576
 
485
577
    pa_stream *s = ringtone_->pulseStream();
 
578
    size_t sample_size = ringtone_->sampleSize();
486
579
 
487
580
    int writable = pa_stream_writable_size(s);
488
581
 
499
592
    AudioLoop *fileToPlay = Manager::instance().getTelephoneFile();
500
593
 
501
594
    if (fileToPlay) {
502
 
        fileToPlay->getNext((SFLDataFormat *) data, bytes / sizeof(SFLDataFormat), 100);
503
 
        applyGain(static_cast<SFLDataFormat *>(data), bytes / sizeof(SFLDataFormat), getPlaybackGain());
504
 
    }
505
 
    else
 
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);
 
599
    } else {
506
600
        memset(data, 0, bytes);
 
601
    }
507
602
 
508
 
    pa_stream_write(s, data, bytes, NULL, 0, PA_SEEK_RELATIVE);
 
603
    pa_stream_write(s, data, bytes, nullptr, 0, PA_SEEK_RELATIVE);
509
604
}
510
605
 
511
606
void
514
609
                                     uint32_t idx UNUSED, void *userdata)
515
610
{
516
611
    PulseLayer *context = static_cast<PulseLayer*>(userdata);
 
612
 
517
613
    switch (type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
518
 
        pa_operation *op;
 
614
            pa_operation *op;
519
615
 
520
616
        case PA_SUBSCRIPTION_EVENT_SINK:
521
617
            switch (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
524
620
                    DEBUG("Updating sink list");
525
621
                    context->sinkList_.clear();
526
622
                    op = pa_context_get_sink_info_list(c, sink_input_info_callback, userdata);
527
 
                    if (op != NULL)
 
623
 
 
624
                    if (op != nullptr)
528
625
                        pa_operation_unref(op);
 
626
 
529
627
                default:
530
628
                    break;
531
629
            }
 
630
 
532
631
            break;
533
632
 
534
633
        case PA_SUBSCRIPTION_EVENT_SOURCE:
538
637
                    DEBUG("Updating source list");
539
638
                    context->sourceList_.clear();
540
639
                    op = pa_context_get_source_info_list(c, source_input_info_callback, userdata);
541
 
                    if (op != NULL)
 
640
 
 
641
                    if (op != nullptr)
542
642
                        pa_operation_unref(op);
 
643
 
543
644
                default:
544
645
                    break;
545
646
            }
 
647
 
546
648
            break;
 
649
 
547
650
        default:
548
651
            DEBUG("Unhandled event type 0x%x", type);
549
652
            break;
562
665
    }
563
666
 
564
667
    DEBUG("Source %u\n"
565
 
           "    Name: %s\n"
566
 
           "    Driver: %s\n"
567
 
           "    Description: %s\n"
568
 
           "    Sample Specification: %s\n"
569
 
           "    Channel Map: %s\n"
570
 
           "    Owner Module: %u\n"
571
 
           "    Volume: %s\n"
572
 
           "    Monitor if Sink: %u\n"
573
 
           "    Latency: %0.0f usec\n"
574
 
           "    Flags: %s%s%s\n",
575
 
           i->index,
576
 
           i->name,
577
 
           i->driver,
578
 
           i->description,
579
 
           pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
580
 
           pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
581
 
           i->owner_module,
582
 
           i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
583
 
           i->monitor_of_sink,
584
 
           (double) i->latency,
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" : "");
 
668
          "    Name: %s\n"
 
669
          "    Driver: %s\n"
 
670
          "    Description: %s\n"
 
671
          "    Sample Specification: %s\n"
 
672
          "    Channel Map: %s\n"
 
673
          "    Owner Module: %u\n"
 
674
          "    Volume: %s\n"
 
675
          "    Monitor if Sink: %u\n"
 
676
          "    Latency: %0.0f usec\n"
 
677
          "    Flags: %s%s%s\n",
 
678
          i->index,
 
679
          i->name,
 
680
          i->driver,
 
681
          i->description,
 
682
          pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
 
683
          pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
 
684
          i->owner_module,
 
685
          i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
 
686
          i->monitor_of_sink,
 
687
          (double) i->latency,
 
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" : "");
588
691
 
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);
 
695
    }
591
696
}
592
697
 
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" : "");
627
732
 
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);
 
736
    }
630
737
}
631
738
 
632
739
void PulseLayer::updatePreference(AudioPreference &preference, int index, PCMType type)
633
740
{
634
741
    const std::string devName(getAudioDeviceName(index, type));
 
742
 
635
743
    switch (type) {
636
744
        case SFL_PCM_PLAYBACK:
637
745
            DEBUG("setting %s for playback", devName.c_str());
638
746
            preference.setPulseDevicePlayback(devName);
639
747
            break;
 
748
 
640
749
        case SFL_PCM_CAPTURE:
641
750
            DEBUG("setting %s for capture", devName.c_str());
642
751
            preference.setPulseDeviceRecord(devName);
643
752
            break;
 
753
 
644
754
        case SFL_PCM_RINGTONE:
645
755
            DEBUG("setting %s for ringer", devName.c_str());
646
756
            preference.setPulseDeviceRingtone(devName);
647
757
            break;
 
758
 
648
759
        default:
649
760
            break;
650
761
    }