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

« back to all changes in this revision

Viewing changes to daemon/src/audio/jack/jacklayer.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2014 Savoir-Faire Linux Inc.
 
3
 *  Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 
18
 *
 
19
 *  Additional permission under GNU GPL version 3 section 7:
 
20
 *
 
21
 *  If you modify this program, or any covered work, by linking or
 
22
 *  combining it with the OpenSSL project's OpenSSL library (or a
 
23
 *  modified version of that library), containing parts covered by the
 
24
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 
25
 *  grants you additional permission to convey the resulting work.
 
26
 *  Corresponding Source for a non-source form of such a combination
 
27
 *  shall include the source code for the parts of OpenSSL used as well
 
28
 *  as that of the covered work.
 
29
 */
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
#include "config.h"
 
33
#endif
 
34
 
 
35
#include "jacklayer.h"
 
36
#include <cassert>
 
37
#include <climits>
 
38
#include "logger.h"
 
39
#include "audio/mainbuffer.h"
 
40
#include "manager.h"
 
41
#include "array_size.h"
 
42
 
 
43
#include <unistd.h>
 
44
 
 
45
#if 0
 
46
TODO
 
47
* implement shutdown callback
 
48
* auto connect optional
 
49
#endif
 
50
 
 
51
namespace
 
52
{
 
53
void connectPorts(jack_client_t *client, int portType, const std::vector<jack_port_t *> &ports)
 
54
{
 
55
    const char **physical_ports = jack_get_ports(client, NULL, NULL, portType | JackPortIsPhysical);
 
56
    for (unsigned i = 0; physical_ports[i]; ++i) {
 
57
        const char *port = jack_port_name(ports[i]);
 
58
        if (portType & JackPortIsInput) {
 
59
            if (jack_connect(client, port, physical_ports[i])) {
 
60
                ERROR("Can't connect %s to %s", port, physical_ports[i]);
 
61
                break;
 
62
            }
 
63
        } else {
 
64
            if (jack_connect(client, physical_ports[i], port)) {
 
65
                ERROR("Can't connect port %s to %s", physical_ports[i], port);
 
66
                break;
 
67
            }
 
68
        }
 
69
    }
 
70
    free(physical_ports);
 
71
}
 
72
 
 
73
bool ringbuffer_ready_for_read(const jack_ringbuffer_t *rb)
 
74
{
 
75
    // XXX 512 is arbitrary
 
76
    return jack_ringbuffer_read_space(rb) > 512;
 
77
}
 
78
}
 
79
 
 
80
void JackLayer::fillWithUrgent(AudioBuffer &buffer, size_t samplesToGet)
 
81
{
 
82
    // Urgent data (dtmf, incoming call signal) come first.
 
83
    samplesToGet = std::min(samplesToGet, hardwareBufferSize_);
 
84
    buffer.resize(samplesToGet);
 
85
    urgentRingBuffer_.get(buffer, MainBuffer::DEFAULT_ID);
 
86
    buffer.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
 
87
 
 
88
    // Consume the regular one as well (same amount of samples)
 
89
    Manager::instance().getMainBuffer().discard(samplesToGet, MainBuffer::DEFAULT_ID);
 
90
}
 
91
 
 
92
void JackLayer::fillWithVoice(AudioBuffer &buffer, size_t samplesAvail)
 
93
{
 
94
    MainBuffer &mainBuffer = Manager::instance().getMainBuffer();
 
95
 
 
96
    buffer.resize(samplesAvail);
 
97
    mainBuffer.getData(buffer, MainBuffer::DEFAULT_ID);
 
98
    buffer.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
 
99
 
 
100
    if (audioFormat_.sample_rate != (unsigned) mainBuffer.getInternalSamplingRate()) {
 
101
        DEBUG("fillWithVoice sample_rate != mainBuffer.getInternalSamplingRate() \n");
 
102
        AudioBuffer out(buffer, false);
 
103
        out.setSampleRate(audioFormat_.sample_rate);
 
104
        resampler_.resample(buffer, out);
 
105
        buffer = out;
 
106
    }
 
107
}
 
108
 
 
109
void JackLayer::fillWithToneOrRingtone(AudioBuffer &buffer)
 
110
{
 
111
    buffer.resize(hardwareBufferSize_);
 
112
    AudioLoop *tone = Manager::instance().getTelephoneTone();
 
113
    AudioLoop *file_tone = Manager::instance().getTelephoneFile();
 
114
 
 
115
    // In case of a dtmf, the pointers will be set to nullptr once the dtmf length is
 
116
    // reached. For this reason we need to fill audio buffer with zeros if pointer is nullptr
 
117
    if (tone) {
 
118
        tone->getNext(buffer, playbackGain_);
 
119
    } else if (file_tone) {
 
120
        file_tone->getNext(buffer, playbackGain_);
 
121
    } else {
 
122
        buffer.reset();
 
123
    }
 
124
}
 
125
 
 
126
void
 
127
JackLayer::playback()
 
128
{
 
129
    notifyIncomingCall();
 
130
 
 
131
    const size_t samplesToGet = Manager::instance().getMainBuffer().availableForGet(MainBuffer::DEFAULT_ID);
 
132
    const size_t urgentSamplesToGet = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);
 
133
 
 
134
    if (urgentSamplesToGet > 0) {
 
135
        fillWithUrgent(playbackBuffer_, urgentSamplesToGet);
 
136
    } else {
 
137
                if (samplesToGet > 0) {
 
138
            fillWithVoice(playbackBuffer_, samplesToGet);
 
139
        } else {
 
140
            fillWithToneOrRingtone(playbackBuffer_);
 
141
        }
 
142
        }
 
143
 
 
144
    playbackFloatBuffer_.resize(playbackBuffer_.frames());
 
145
    write(playbackBuffer_, playbackFloatBuffer_);
 
146
}
 
147
 
 
148
void
 
149
JackLayer::capture()
 
150
{
 
151
    // get audio from jack ringbuffer
 
152
    read(captureBuffer_);
 
153
 
 
154
    MainBuffer &mbuffer = Manager::instance().getMainBuffer();
 
155
    const AudioFormat mainBufferFormat = mbuffer.getInternalAudioFormat();
 
156
    const bool resample = mainBufferFormat.sample_rate != audioFormat_.sample_rate;
 
157
 
 
158
    captureBuffer_.applyGain(isCaptureMuted_ ? 0.0 : captureGain_);
 
159
 
 
160
    if (resample) {
 
161
                int outSamples = captureBuffer_.frames() * (static_cast<double>(audioFormat_.sample_rate) / mainBufferFormat.sample_rate);
 
162
        AudioBuffer out(outSamples, mainBufferFormat);
 
163
        resampler_.resample(captureBuffer_, out);
 
164
        dcblocker_.process(out);
 
165
        mbuffer.putData(out, MainBuffer::DEFAULT_ID);
 
166
    } else {
 
167
        dcblocker_.process(captureBuffer_);
 
168
        mbuffer.putData(captureBuffer_, MainBuffer::DEFAULT_ID);
 
169
    }
 
170
}
 
171
 
 
172
static void
 
173
convertToFloat(const std::vector<SFLAudioSample> &src, std::vector<float> &dest)
 
174
{
 
175
    static const float INV_SHORT_MAX = 1 / (float) SHRT_MAX;
 
176
    if (dest.size() != src.size()) {
 
177
        ERROR("MISMATCH");
 
178
        return;
 
179
    }
 
180
    for (size_t i = 0; i < dest.size(); ++i)
 
181
        dest[i] = src[i] * INV_SHORT_MAX;
 
182
}
 
183
 
 
184
static void
 
185
convertFromFloat(std::vector<float> &src, std::vector<SFLAudioSample> &dest)
 
186
{
 
187
    if (dest.size() != src.size()) {
 
188
        ERROR("MISMATCH");
 
189
        return;
 
190
    }
 
191
    for (size_t i = 0; i < dest.size(); ++i)
 
192
        dest[i] = src[i] * SHRT_MAX;
 
193
}
 
194
 
 
195
void
 
196
JackLayer::write(AudioBuffer &buffer, std::vector<float> &floatBuffer)
 
197
{
 
198
    for (unsigned i = 0; i < out_ringbuffers_.size(); ++i) {
 
199
        const unsigned inChannel = std::min(i, buffer.channels() - 1);
 
200
        convertToFloat(*buffer.getChannel(inChannel), floatBuffer);
 
201
 
 
202
        // write to output
 
203
        const size_t to_ringbuffer = jack_ringbuffer_write_space(out_ringbuffers_[i]);
 
204
        const size_t write_bytes = std::min(buffer.frames() * sizeof(floatBuffer[0]), to_ringbuffer);
 
205
        // FIXME: while we have samples to write AND while we have space to write them
 
206
        const size_t written_bytes = jack_ringbuffer_write(out_ringbuffers_[i],
 
207
                (const char *) floatBuffer.data(), write_bytes);
 
208
        if (written_bytes < write_bytes)
 
209
            WARN("Dropped %zu bytes for channel %u", write_bytes - written_bytes, i);
 
210
    }
 
211
}
 
212
 
 
213
void
 
214
JackLayer::read(AudioBuffer &buffer)
 
215
{
 
216
    for (unsigned i = 0; i < in_ringbuffers_.size(); ++i) {
 
217
 
 
218
        const size_t incomingSamples = jack_ringbuffer_read_space(in_ringbuffers_[i]) / sizeof(captureFloatBuffer_[0]);
 
219
        if (!incomingSamples)
 
220
            continue;
 
221
 
 
222
        captureFloatBuffer_.resize(incomingSamples);
 
223
        buffer.resize(incomingSamples);
 
224
 
 
225
        // write to output
 
226
        const size_t from_ringbuffer = jack_ringbuffer_read_space(in_ringbuffers_[i]);
 
227
        const size_t expected_bytes = std::min(incomingSamples * sizeof(captureFloatBuffer_[0]), from_ringbuffer);
 
228
        // FIXME: while we have samples to write AND while we have space to write them
 
229
        const size_t read_bytes = jack_ringbuffer_read(in_ringbuffers_[i],
 
230
                (char *) captureFloatBuffer_.data(), expected_bytes);
 
231
        if (read_bytes < expected_bytes) {
 
232
            WARN("Dropped %zu bytes", expected_bytes - read_bytes);
 
233
            break;
 
234
        }
 
235
 
 
236
        /* Write the data one frame at a time.  This is
 
237
         * inefficient, but makes things simpler. */
 
238
        // FIXME: this is braindead, we should write blocks of samples at a time
 
239
        // convert a vector of samples from 1 channel to a float vector
 
240
        convertFromFloat(captureFloatBuffer_, *buffer.getChannel(i));
 
241
    }
 
242
}
 
243
 
 
244
/* This thread can lock, do whatever it wants, and read from/write to the jack
 
245
 * ring buffers
 
246
 * XXX: Access to shared state (i.e. member variables) should be synchronized if needed */
 
247
void
 
248
JackLayer::ringbuffer_worker()
 
249
{
 
250
    flushMain();
 
251
    flushUrgent();
 
252
 
 
253
        while (true) {
 
254
 
 
255
        std::unique_lock<std::mutex> lock(ringbuffer_thread_mutex_);
 
256
 
 
257
        // may have changed, we don't want to wait for a notification we won't get
 
258
        if (not workerAlive_)
 
259
            return;
 
260
 
 
261
        // FIXME this is all kinds of evil
 
262
        usleep(20000);
 
263
 
 
264
        capture();
 
265
        playback();
 
266
 
 
267
        // wait until process() signals more data
 
268
        // FIXME: this checks for spurious wakes, but the predicate
 
269
        // is rather arbitrary. We should wait until sflphone has/needs data
 
270
        // and jack has/needs data.
 
271
        data_ready_.wait(lock, [&] {
 
272
            // Note: lock is released while waiting, and held when woken
 
273
            // up, so this predicate is called while holding the lock
 
274
            return not workerAlive_
 
275
            or ringbuffer_ready_for_read(in_ringbuffers_[0]);
 
276
        });
 
277
    }
 
278
}
 
279
 
 
280
void
 
281
createPorts(jack_client_t *client, std::vector<jack_port_t *> &ports,
 
282
            bool playback, std::vector<jack_ringbuffer_t *> &ringbuffers)
 
283
{
 
284
 
 
285
    const char **physical_ports = jack_get_ports(client, NULL, NULL,
 
286
            playback ? JackPortIsInput : JackPortIsOutput | JackPortIsPhysical);
 
287
    for (unsigned i = 0; physical_ports[i]; ++i) {
 
288
        char port_name[32] = {0};
 
289
        if (playback)
 
290
            snprintf(port_name, sizeof(port_name), "out_%d", i + 1);
 
291
        else
 
292
            snprintf(port_name, sizeof(port_name), "in_%d", i + 1);
 
293
        port_name[sizeof(port_name) - 1] = '\0';
 
294
        jack_port_t *port = jack_port_register(client,
 
295
                port_name, JACK_DEFAULT_AUDIO_TYPE, playback ? JackPortIsOutput : JackPortIsInput, 0);
 
296
        if (port == nullptr)
 
297
            throw std::runtime_error("Could not register JACK output port");
 
298
        ports.push_back(port);
 
299
 
 
300
        static const unsigned RB_SIZE = 16384;
 
301
        jack_ringbuffer_t *rb = jack_ringbuffer_create(RB_SIZE);
 
302
        if (rb == nullptr)
 
303
            throw std::runtime_error("Could not create JACK ringbuffer");
 
304
        if (jack_ringbuffer_mlock(rb))
 
305
            throw std::runtime_error("Could not lock JACK ringbuffer in memory");
 
306
        ringbuffers.push_back(rb);
 
307
    }
 
308
    free(physical_ports);
 
309
}
 
310
 
 
311
 
 
312
JackLayer::JackLayer(const AudioPreference &p) :
 
313
    AudioLayer(p),
 
314
    captureClient_(nullptr),
 
315
    playbackClient_(nullptr),
 
316
    out_ports_(),
 
317
    in_ports_(),
 
318
    out_ringbuffers_(),
 
319
    in_ringbuffers_(),
 
320
    ringbuffer_thread_(),
 
321
    workerAlive_(false),
 
322
    ringbuffer_thread_mutex_(),
 
323
    data_ready_(),
 
324
    playbackBuffer_(0, audioFormat_),
 
325
    playbackFloatBuffer_(),
 
326
    captureBuffer_(0, audioFormat_),
 
327
    captureFloatBuffer_(),
 
328
    hardwareBufferSize_(0)
 
329
{
 
330
    playbackClient_ = jack_client_open(PACKAGE_NAME,
 
331
            (jack_options_t) (JackNullOption | JackNoStartServer), NULL);
 
332
    if (!playbackClient_)
 
333
        throw std::runtime_error("Could not open JACK client");
 
334
 
 
335
    captureClient_ = jack_client_open(PACKAGE_NAME,
 
336
            (jack_options_t) (JackNullOption | JackNoStartServer), NULL);
 
337
    if (!captureClient_)
 
338
        throw std::runtime_error("Could not open JACK client");
 
339
 
 
340
    jack_set_process_callback(captureClient_, process_capture, this);
 
341
    jack_set_process_callback(playbackClient_, process_playback, this);
 
342
 
 
343
    createPorts(playbackClient_, out_ports_, true, out_ringbuffers_);
 
344
    createPorts(captureClient_, in_ports_, false, in_ringbuffers_);
 
345
 
 
346
    const auto playRate = jack_get_sample_rate(playbackClient_);
 
347
    const auto captureRate = jack_get_sample_rate(captureClient_);
 
348
    if (playRate != captureRate)
 
349
        ERROR("Mismatch between capture rate %u and playback rate %u", playRate, captureRate);
 
350
 
 
351
    hardwareBufferSize_ = jack_get_buffer_size(playbackClient_);
 
352
 
 
353
    auto update_buffer = [] (AudioBuffer &buf, size_t size, unsigned rate, unsigned nbChannels) {
 
354
        buf.setSampleRate(rate);
 
355
        buf.resize(size);
 
356
        buf.setChannelNum(nbChannels);
 
357
    };
 
358
 
 
359
    update_buffer(playbackBuffer_, hardwareBufferSize_, playRate, out_ports_.size());
 
360
    update_buffer(captureBuffer_, hardwareBufferSize_, captureRate, in_ports_.size());
 
361
 
 
362
    jack_on_shutdown(playbackClient_, onShutdown, this);
 
363
}
 
364
 
 
365
JackLayer::~JackLayer()
 
366
{
 
367
    stopStream();
 
368
 
 
369
    for (auto p : out_ports_)
 
370
        jack_port_unregister(playbackClient_, p);
 
371
    for (auto p : in_ports_)
 
372
        jack_port_unregister(captureClient_, p);
 
373
 
 
374
    if (jack_client_close(playbackClient_))
 
375
        ERROR("JACK client could not close");
 
376
    if (jack_client_close(captureClient_))
 
377
        ERROR("JACK client could not close");
 
378
 
 
379
    for (auto r : out_ringbuffers_)
 
380
        jack_ringbuffer_free(r);
 
381
    for (auto r : in_ringbuffers_)
 
382
        jack_ringbuffer_free(r);
 
383
}
 
384
 
 
385
void
 
386
JackLayer::updatePreference(AudioPreference & /*pref*/, int /*index*/, DeviceType /*type*/)
 
387
{}
 
388
 
 
389
std::vector<std::string>
 
390
JackLayer::getCaptureDeviceList() const
 
391
{
 
392
    return std::vector<std::string>();
 
393
}
 
394
 
 
395
std::vector<std::string>
 
396
JackLayer::getPlaybackDeviceList() const
 
397
{
 
398
    return std::vector<std::string>();
 
399
}
 
400
 
 
401
int
 
402
JackLayer::getAudioDeviceIndex(const std::string& /*name*/, DeviceType /*type*/) const { return 0; }
 
403
 
 
404
std::string
 
405
JackLayer::getAudioDeviceName(int /*index*/, DeviceType /*type*/) const { return ""; }
 
406
 
 
407
int
 
408
JackLayer::getIndexCapture() const { return 0; }
 
409
 
 
410
int
 
411
JackLayer::getIndexPlayback() const { return 0; }
 
412
 
 
413
int
 
414
JackLayer::getIndexRingtone() const { return 0; }
 
415
 
 
416
int
 
417
JackLayer::process_capture(jack_nframes_t frames, void *arg)
 
418
{
 
419
    JackLayer *context = static_cast<JackLayer*>(arg);
 
420
 
 
421
    for (unsigned i = 0; i < context->in_ringbuffers_.size(); ++i) {
 
422
 
 
423
        // read from input
 
424
        jack_default_audio_sample_t *in_buffers = static_cast<jack_default_audio_sample_t*>(jack_port_get_buffer(context->in_ports_[i], frames));
 
425
 
 
426
        const size_t bytes_to_read = frames * sizeof(*in_buffers);
 
427
        size_t bytes_to_rb = jack_ringbuffer_write(context->in_ringbuffers_[i], (char *) in_buffers, bytes_to_read);
 
428
 
 
429
        // fill the rest with silence
 
430
        if (bytes_to_rb < bytes_to_read) {
 
431
            // TODO: set some flag for underrun?
 
432
            WARN("Dropped %lu bytes", bytes_to_read - bytes_to_rb);
 
433
        }
 
434
    }
 
435
 
 
436
        /* Tell the ringbuffer thread there is work to do.  If it is already
 
437
         * running, the lock will not be available.  We can't wait
 
438
         * here in the process() thread, but we don't need to signal
 
439
         * in that case, because the ringbuffer thread will read all the
 
440
         * data queued before waiting again. */
 
441
        if (context->ringbuffer_thread_mutex_.try_lock()) {
 
442
            context->data_ready_.notify_one();
 
443
        context->ringbuffer_thread_mutex_.unlock();
 
444
    }
 
445
 
 
446
    return 0;
 
447
}
 
448
 
 
449
int
 
450
JackLayer::process_playback(jack_nframes_t frames, void *arg)
 
451
{
 
452
    JackLayer *context = static_cast<JackLayer*>(arg);
 
453
 
 
454
    for (unsigned i = 0; i < context->out_ringbuffers_.size(); ++i) {
 
455
        // write to output
 
456
        jack_default_audio_sample_t *out_buffers = static_cast<jack_default_audio_sample_t*>(jack_port_get_buffer(context->out_ports_[i], frames));
 
457
 
 
458
        const size_t bytes_to_write = frames * sizeof(*out_buffers);
 
459
        size_t bytes_from_rb = jack_ringbuffer_read(context->out_ringbuffers_[i], (char *) out_buffers, bytes_to_write);
 
460
 
 
461
        // fill the rest with silence
 
462
        if (bytes_from_rb < bytes_to_write) {
 
463
            const size_t frames_read = bytes_from_rb / sizeof(*out_buffers);
 
464
            memset(out_buffers + frames_read, 0, bytes_to_write - bytes_from_rb);
 
465
        }
 
466
    }
 
467
 
 
468
    return 0;
 
469
}
 
470
 
 
471
/**
 
472
 * Start the capture and playback.
 
473
 */
 
474
void
 
475
JackLayer::startStream()
 
476
{
 
477
    if (isStarted_)
 
478
        return;
 
479
 
 
480
    dcblocker_.reset();
 
481
    const auto hardwareFormat = AudioFormat(playbackBuffer_.getSampleRate(), out_ports_.size());
 
482
    hardwareFormatAvailable(hardwareFormat);
 
483
 
 
484
    workerAlive_ = true;
 
485
    assert(not ringbuffer_thread_.joinable());
 
486
    ringbuffer_thread_ = std::thread(&JackLayer::ringbuffer_worker, this);
 
487
 
 
488
    if (jack_activate(playbackClient_) or jack_activate(captureClient_)) {
 
489
        ERROR("Could not activate JACK client");
 
490
        workerAlive_ = false;
 
491
        ringbuffer_thread_.join();
 
492
        isStarted_ = false;
 
493
        return;
 
494
    } else {
 
495
        isStarted_ = true;
 
496
    }
 
497
 
 
498
    connectPorts(playbackClient_, JackPortIsInput, out_ports_);
 
499
    connectPorts(captureClient_, JackPortIsOutput, in_ports_);
 
500
}
 
501
 
 
502
void
 
503
JackLayer::onShutdown(void * /* data */)
 
504
{
 
505
    WARN("JACK server shutdown");
 
506
    // FIXME: handle this safely
 
507
}
 
508
 
 
509
/**
 
510
 * Stop playback and capture.
 
511
 */
 
512
void
 
513
JackLayer::stopStream()
 
514
{
 
515
    {
 
516
        std::lock_guard<std::mutex> lock(ringbuffer_thread_mutex_);
 
517
        workerAlive_ = false;
 
518
        data_ready_.notify_one();
 
519
    }
 
520
 
 
521
    if (jack_deactivate(playbackClient_) or jack_deactivate(captureClient_)) {
 
522
        ERROR("JACK client could not deactivate");
 
523
    }
 
524
 
 
525
    isStarted_ = false;
 
526
 
 
527
    if (ringbuffer_thread_.joinable())
 
528
        ringbuffer_thread_.join();
 
529
 
 
530
    flushMain();
 
531
    flushUrgent();
 
532
}