2011-07-08 08:23:47 +04:00
|
|
|
/*
|
|
|
|
* Copyright © 2011 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* This program is made available under an ISC-style license. See the
|
|
|
|
* accompanying file LICENSE for details.
|
|
|
|
*/
|
2014-02-26 22:48:20 +04:00
|
|
|
#ifdef NDEBUG
|
|
|
|
#undef NDEBUG
|
|
|
|
#endif
|
2015-12-01 02:55:42 +03:00
|
|
|
#define _XOPEN_SOURCE 600
|
2011-07-08 08:23:47 +04:00
|
|
|
#include "cubeb/cubeb.h"
|
|
|
|
#include <assert.h>
|
2012-05-04 05:02:37 +04:00
|
|
|
#include <stdio.h>
|
2011-07-08 08:23:47 +04:00
|
|
|
#include <string.h>
|
2014-02-26 22:48:20 +04:00
|
|
|
#include <math.h>
|
2013-09-02 22:50:58 +04:00
|
|
|
#include "common.h"
|
2015-11-26 01:04:12 +03:00
|
|
|
#ifdef CUBEB_GECKO_BUILD
|
|
|
|
#include "TestHarness.h"
|
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
#define BEGIN_TEST fprintf(stderr, "START %s\n", __func__)
|
|
|
|
#define END_TEST fprintf(stderr, "END %s\n", __func__)
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2011-08-29 07:56:02 +04:00
|
|
|
#define STREAM_RATE 44100
|
2016-06-29 16:04:08 +03:00
|
|
|
#define STREAM_LATENCY 100 * STREAM_RATE / 1000
|
2011-08-29 07:56:02 +04:00
|
|
|
#define STREAM_CHANNELS 1
|
2015-11-26 00:57:04 +03:00
|
|
|
#if (defined(_WIN32) || defined(__WIN32__))
|
|
|
|
#define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE
|
|
|
|
#else
|
2011-08-29 07:56:02 +04:00
|
|
|
#define STREAM_FORMAT CUBEB_SAMPLE_S16LE
|
2015-11-26 00:57:04 +03:00
|
|
|
#endif
|
2011-08-29 07:56:02 +04:00
|
|
|
|
2016-10-13 02:04:35 +03:00
|
|
|
template<typename T, size_t N>
|
|
|
|
constexpr size_t
|
2016-10-13 05:15:57 +03:00
|
|
|
ARRAY_LENGTH(T(&)[N])
|
2016-10-13 02:04:35 +03:00
|
|
|
{
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
static int dummy;
|
|
|
|
static uint64_t total_frames_written;
|
2012-05-02 08:53:57 +04:00
|
|
|
static int delay_callback;
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
static long
|
2016-08-23 04:20:54 +03:00
|
|
|
test_data_callback(cubeb_stream * stm, void * user_ptr, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
|
2011-07-08 08:23:47 +04:00
|
|
|
{
|
Preparatory work for the input and duplex code
This is changing all the signatures of the `cubeb_stream_init` implementations,
the signature of the `data_callback` type, so that cubeb can support audio
input.
`cubeb_stream_init` now has two `cubeb_stream_params` pointers, one for input,
one for output. If two pointers are passed, a "duplex" stream is opened. If only
one pointer is passed, an input-only or output-only stream is created.
Duplex streams have the same sample rate, and sample type. They don't have to
have the same number of channels.
`data_callback` now has two pointers to audio buffers: an input buffer (`NULL`
if this is an output-only stream) containing input data (e.g. a microphone), and
an output buffer, to be filled, as usual, with the audio frames to play. The
two buffers always have the exact same number of audio frames, and are
temporally correlated in a way that ensures the minimal loop-back latency on
the system if one directly copies the input buffer to the output buffer.
No functionnal changes are present in this patch, just signature changes.
Asserts have been added to prevent users to try to use the input code path for
now.
Actual implementations with the input code for different platforms will follow.
Green `mozilla-central` push:
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=15b4dd3cbbe8>
2016-01-13 19:16:50 +03:00
|
|
|
assert(stm && user_ptr == &dummy && outputbuffer && nframes > 0);
|
2015-12-01 04:11:27 +03:00
|
|
|
#if (defined(_WIN32) || defined(__WIN32__))
|
Preparatory work for the input and duplex code
This is changing all the signatures of the `cubeb_stream_init` implementations,
the signature of the `data_callback` type, so that cubeb can support audio
input.
`cubeb_stream_init` now has two `cubeb_stream_params` pointers, one for input,
one for output. If two pointers are passed, a "duplex" stream is opened. If only
one pointer is passed, an input-only or output-only stream is created.
Duplex streams have the same sample rate, and sample type. They don't have to
have the same number of channels.
`data_callback` now has two pointers to audio buffers: an input buffer (`NULL`
if this is an output-only stream) containing input data (e.g. a microphone), and
an output buffer, to be filled, as usual, with the audio frames to play. The
two buffers always have the exact same number of audio frames, and are
temporally correlated in a way that ensures the minimal loop-back latency on
the system if one directly copies the input buffer to the output buffer.
No functionnal changes are present in this patch, just signature changes.
Asserts have been added to prevent users to try to use the input code path for
now.
Actual implementations with the input code for different platforms will follow.
Green `mozilla-central` push:
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=15b4dd3cbbe8>
2016-01-13 19:16:50 +03:00
|
|
|
memset(outputbuffer, 0, nframes * sizeof(float));
|
2015-11-26 00:57:04 +03:00
|
|
|
#else
|
Preparatory work for the input and duplex code
This is changing all the signatures of the `cubeb_stream_init` implementations,
the signature of the `data_callback` type, so that cubeb can support audio
input.
`cubeb_stream_init` now has two `cubeb_stream_params` pointers, one for input,
one for output. If two pointers are passed, a "duplex" stream is opened. If only
one pointer is passed, an input-only or output-only stream is created.
Duplex streams have the same sample rate, and sample type. They don't have to
have the same number of channels.
`data_callback` now has two pointers to audio buffers: an input buffer (`NULL`
if this is an output-only stream) containing input data (e.g. a microphone), and
an output buffer, to be filled, as usual, with the audio frames to play. The
two buffers always have the exact same number of audio frames, and are
temporally correlated in a way that ensures the minimal loop-back latency on
the system if one directly copies the input buffer to the output buffer.
No functionnal changes are present in this patch, just signature changes.
Asserts have been added to prevent users to try to use the input code path for
now.
Actual implementations with the input code for different platforms will follow.
Green `mozilla-central` push:
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=15b4dd3cbbe8>
2016-01-13 19:16:50 +03:00
|
|
|
memset(outputbuffer, 0, nframes * sizeof(short));
|
2015-11-26 00:57:04 +03:00
|
|
|
#endif
|
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
total_frames_written += nframes;
|
2012-05-02 08:53:57 +04:00
|
|
|
if (delay_callback) {
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(10);
|
2012-05-02 08:53:57 +04:00
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
return nframes;
|
|
|
|
}
|
|
|
|
|
2012-06-06 07:33:12 +04:00
|
|
|
void
|
2016-08-23 04:20:54 +03:00
|
|
|
test_state_callback(cubeb_stream * /*stm*/, void * /*user_ptr*/, cubeb_state /*state*/)
|
2011-07-08 08:23:47 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_init_destroy_context(void)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
2014-10-13 09:52:37 +04:00
|
|
|
char const* backend_id;
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
2011-07-08 08:23:47 +04:00
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2014-10-13 09:52:37 +04:00
|
|
|
|
|
|
|
backend_id = cubeb_get_backend_id(ctx);
|
|
|
|
assert(backend_id);
|
|
|
|
|
|
|
|
fprintf(stderr, "Backend: %s\n", backend_id);
|
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
static void
|
|
|
|
test_init_destroy_multiple_contexts(void)
|
|
|
|
{
|
2014-09-29 05:04:25 +04:00
|
|
|
size_t i;
|
2011-07-08 08:23:47 +04:00
|
|
|
int r;
|
|
|
|
cubeb * ctx[4];
|
2014-09-17 09:34:37 +04:00
|
|
|
int order[4] = {2, 0, 3, 1};
|
|
|
|
assert(ARRAY_LENGTH(ctx) == ARRAY_LENGTH(order));
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
|
|
|
|
r = cubeb_init(&ctx[i], NULL);
|
|
|
|
assert(r == 0 && ctx[i]);
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
/* destroy in a different order */
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
|
|
|
|
cubeb_destroy(ctx[order[i]]);
|
|
|
|
}
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2014-10-12 22:51:37 +04:00
|
|
|
static void
|
|
|
|
test_context_variables(void)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
|
|
|
uint32_t value;
|
|
|
|
cubeb_stream_params params;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-10-12 22:51:37 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_context_variables");
|
2014-10-12 22:51:37 +04:00
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
params.channels = STREAM_CHANNELS;
|
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2014-10-12 22:51:37 +04:00
|
|
|
r = cubeb_get_min_latency(ctx, params, &value);
|
2014-11-28 05:56:44 +03:00
|
|
|
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
|
|
|
|
if (r == CUBEB_OK) {
|
|
|
|
assert(value > 0);
|
|
|
|
}
|
2014-10-12 22:51:37 +04:00
|
|
|
|
|
|
|
r = cubeb_get_preferred_sample_rate(ctx, &value);
|
2014-11-28 05:56:44 +03:00
|
|
|
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
|
|
|
|
if (r == CUBEB_OK) {
|
|
|
|
assert(value > 0);
|
|
|
|
}
|
2014-10-12 22:51:37 +04:00
|
|
|
|
|
|
|
cubeb_destroy(ctx);
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2014-10-12 22:51:37 +04:00
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
static void
|
|
|
|
test_init_destroy_stream(void)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
|
|
|
cubeb_stream * stream;
|
|
|
|
cubeb_stream_params params;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
2011-07-08 08:23:47 +04:00
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2011-08-29 07:56:02 +04:00
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2011-07-08 08:23:47 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
|
|
|
assert(r == 0 && stream);
|
|
|
|
|
|
|
|
cubeb_stream_destroy(stream);
|
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
static void
|
|
|
|
test_init_destroy_multiple_streams(void)
|
|
|
|
{
|
2014-09-29 05:04:25 +04:00
|
|
|
size_t i;
|
2011-07-08 08:23:47 +04:00
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
2014-09-17 09:22:06 +04:00
|
|
|
cubeb_stream * stream[8];
|
2011-07-08 08:23:47 +04:00
|
|
|
cubeb_stream_params params;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
2011-07-08 08:23:47 +04:00
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2011-08-29 07:56:02 +04:00
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream[i], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2011-07-08 08:23:47 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
2014-04-04 05:57:30 +04:00
|
|
|
assert(r == 0);
|
|
|
|
assert(stream[i]);
|
2011-07-08 08:23:47 +04:00
|
|
|
}
|
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
|
2011-07-08 08:23:47 +04:00
|
|
|
cubeb_stream_destroy(stream[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2014-10-14 09:21:49 +04:00
|
|
|
static void
|
|
|
|
test_configure_stream(void)
|
|
|
|
{
|
2014-11-28 05:56:44 +03:00
|
|
|
int r;
|
2014-10-14 09:21:49 +04:00
|
|
|
cubeb * ctx;
|
|
|
|
cubeb_stream * stream;
|
|
|
|
cubeb_stream_params params;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-10-14 09:21:49 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
2014-11-28 05:56:44 +03:00
|
|
|
assert(r == 0 && ctx);
|
2014-10-14 09:21:49 +04:00
|
|
|
|
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = 2; // panning
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2014-10-14 09:21:49 +04:00
|
|
|
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2014-10-14 09:21:49 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
2014-11-28 05:56:44 +03:00
|
|
|
assert(r == 0 && stream);
|
2014-10-14 09:21:49 +04:00
|
|
|
|
2014-11-28 05:56:44 +03:00
|
|
|
r = cubeb_stream_set_volume(stream, 1.0f);
|
|
|
|
assert(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
|
2014-10-14 09:21:49 +04:00
|
|
|
|
2014-11-28 05:56:44 +03:00
|
|
|
r = cubeb_stream_set_panning(stream, 0.0f);
|
|
|
|
assert(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
|
2014-10-14 09:21:49 +04:00
|
|
|
|
|
|
|
cubeb_stream_destroy(stream);
|
|
|
|
cubeb_destroy(ctx);
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2014-10-14 09:21:49 +04:00
|
|
|
|
2012-05-02 08:53:57 +04:00
|
|
|
static void
|
2012-12-05 06:55:34 +04:00
|
|
|
test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
|
2012-05-02 08:53:57 +04:00
|
|
|
{
|
2014-09-29 05:04:25 +04:00
|
|
|
size_t i;
|
2012-05-02 08:53:57 +04:00
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
2014-09-17 09:22:06 +04:00
|
|
|
cubeb_stream * stream[8];
|
2012-05-02 08:53:57 +04:00
|
|
|
cubeb_stream_params params;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
2012-05-02 08:53:57 +04:00
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2012-05-02 08:53:57 +04:00
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream[i], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2012-05-02 08:53:57 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
2014-04-04 05:57:30 +04:00
|
|
|
assert(r == 0);
|
|
|
|
assert(stream[i]);
|
2012-05-02 08:53:57 +04:00
|
|
|
if (early) {
|
|
|
|
r = cubeb_stream_start(stream[i]);
|
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!early) {
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
|
2012-05-02 08:53:57 +04:00
|
|
|
r = cubeb_stream_start(stream[i]);
|
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-05 06:55:34 +04:00
|
|
|
if (delay_ms) {
|
|
|
|
delay(delay_ms);
|
2012-05-02 08:53:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!early) {
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
|
2012-05-02 08:53:57 +04:00
|
|
|
r = cubeb_stream_stop(stream[i]);
|
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
|
2012-05-02 08:53:57 +04:00
|
|
|
if (early) {
|
|
|
|
r = cubeb_stream_stop(stream[i]);
|
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
cubeb_stream_destroy(stream[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2012-05-02 08:53:57 +04:00
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
static void
|
|
|
|
test_init_destroy_multiple_contexts_and_streams(void)
|
|
|
|
{
|
2014-09-29 05:04:25 +04:00
|
|
|
size_t i, j;
|
2011-07-08 08:23:47 +04:00
|
|
|
int r;
|
2014-09-17 09:22:06 +04:00
|
|
|
cubeb * ctx[2];
|
|
|
|
cubeb_stream * stream[8];
|
2011-07-08 08:23:47 +04:00
|
|
|
cubeb_stream_params params;
|
2014-09-29 05:04:25 +04:00
|
|
|
size_t streams_per_ctx = ARRAY_LENGTH(stream) / ARRAY_LENGTH(ctx);
|
2014-09-17 09:34:37 +04:00
|
|
|
assert(ARRAY_LENGTH(ctx) * streams_per_ctx == ARRAY_LENGTH(stream));
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
params.format = STREAM_FORMAT;
|
2011-08-29 07:56:02 +04:00
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
|
2011-07-08 08:23:47 +04:00
|
|
|
r = cubeb_init(&ctx[i], "test_sanity");
|
|
|
|
assert(r == 0 && ctx[i]);
|
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (j = 0; j < streams_per_ctx; ++j) {
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2011-07-08 08:23:47 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
2014-04-04 05:57:30 +04:00
|
|
|
assert(r == 0);
|
2014-09-17 09:34:37 +04:00
|
|
|
assert(stream[i * streams_per_ctx + j]);
|
2011-07-08 08:23:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 09:34:37 +04:00
|
|
|
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
|
|
|
|
for (j = 0; j < streams_per_ctx; ++j) {
|
|
|
|
cubeb_stream_destroy(stream[i * streams_per_ctx + j]);
|
2011-07-08 08:23:47 +04:00
|
|
|
}
|
|
|
|
cubeb_destroy(ctx[i]);
|
|
|
|
}
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
static void
|
|
|
|
test_basic_stream_operations(void)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
|
|
|
cubeb_stream * stream;
|
|
|
|
cubeb_stream_params params;
|
|
|
|
uint64_t position;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
2011-07-08 08:23:47 +04:00
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2011-08-29 07:56:02 +04:00
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2011-07-08 08:23:47 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
|
|
|
assert(r == 0 && stream);
|
|
|
|
|
|
|
|
/* position and volume before stream has started */
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0 && position == 0);
|
|
|
|
|
|
|
|
r = cubeb_stream_start(stream);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
/* position and volume after while stream running */
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
r = cubeb_stream_stop(stream);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
/* position and volume after stream has stopped */
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
cubeb_stream_destroy(stream);
|
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
static void
|
|
|
|
test_stream_position(void)
|
|
|
|
{
|
2014-09-29 05:04:25 +04:00
|
|
|
size_t i;
|
2011-07-08 08:23:47 +04:00
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
|
|
|
cubeb_stream * stream;
|
|
|
|
cubeb_stream_params params;
|
|
|
|
uint64_t position, last_position;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
total_frames_written = 0;
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2011-08-29 07:56:02 +04:00
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2011-07-08 08:23:47 +04:00
|
|
|
test_data_callback, test_state_callback, &dummy);
|
|
|
|
assert(r == 0 && stream);
|
|
|
|
|
|
|
|
/* stream position should not advance before starting playback */
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0 && position == 0);
|
|
|
|
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0 && position == 0);
|
|
|
|
|
|
|
|
/* stream position should advance during playback */
|
|
|
|
r = cubeb_stream_start(stream);
|
|
|
|
assert(r == 0);
|
|
|
|
|
2011-08-03 08:45:29 +04:00
|
|
|
/* XXX let start happen */
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-08-03 08:45:29 +04:00
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
/* stream should have prefilled */
|
|
|
|
assert(total_frames_written > 0);
|
|
|
|
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
last_position = position;
|
|
|
|
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
assert(position >= last_position);
|
|
|
|
last_position = position;
|
|
|
|
|
|
|
|
/* stream position should not exceed total frames written */
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
assert(position >= last_position);
|
|
|
|
assert(position <= total_frames_written);
|
|
|
|
last_position = position;
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
}
|
|
|
|
|
2011-08-03 08:45:29 +04:00
|
|
|
assert(last_position != 0);
|
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
/* stream position should not advance after stopping playback */
|
|
|
|
r = cubeb_stream_stop(stream);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
/* XXX allow stream to settle */
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
last_position = position;
|
|
|
|
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
assert(position == last_position);
|
|
|
|
|
|
|
|
cubeb_stream_destroy(stream);
|
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
static int do_drain;
|
|
|
|
static int got_drain;
|
|
|
|
|
|
|
|
static long
|
2016-08-23 04:20:54 +03:00
|
|
|
test_drain_data_callback(cubeb_stream * stm, void * user_ptr, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
|
2011-07-08 08:23:47 +04:00
|
|
|
{
|
Preparatory work for the input and duplex code
This is changing all the signatures of the `cubeb_stream_init` implementations,
the signature of the `data_callback` type, so that cubeb can support audio
input.
`cubeb_stream_init` now has two `cubeb_stream_params` pointers, one for input,
one for output. If two pointers are passed, a "duplex" stream is opened. If only
one pointer is passed, an input-only or output-only stream is created.
Duplex streams have the same sample rate, and sample type. They don't have to
have the same number of channels.
`data_callback` now has two pointers to audio buffers: an input buffer (`NULL`
if this is an output-only stream) containing input data (e.g. a microphone), and
an output buffer, to be filled, as usual, with the audio frames to play. The
two buffers always have the exact same number of audio frames, and are
temporally correlated in a way that ensures the minimal loop-back latency on
the system if one directly copies the input buffer to the output buffer.
No functionnal changes are present in this patch, just signature changes.
Asserts have been added to prevent users to try to use the input code path for
now.
Actual implementations with the input code for different platforms will follow.
Green `mozilla-central` push:
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=15b4dd3cbbe8>
2016-01-13 19:16:50 +03:00
|
|
|
assert(stm && user_ptr == &dummy && outputbuffer && nframes > 0);
|
2011-07-08 08:23:47 +04:00
|
|
|
if (do_drain == 1) {
|
|
|
|
do_drain = 2;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* once drain has started, callback must never be called again */
|
|
|
|
assert(do_drain != 2);
|
2016-06-03 13:17:03 +03:00
|
|
|
#if (defined(_WIN32) || defined(__WIN32__))
|
|
|
|
memset(outputbuffer, 0, nframes * sizeof(float));
|
|
|
|
#else
|
Preparatory work for the input and duplex code
This is changing all the signatures of the `cubeb_stream_init` implementations,
the signature of the `data_callback` type, so that cubeb can support audio
input.
`cubeb_stream_init` now has two `cubeb_stream_params` pointers, one for input,
one for output. If two pointers are passed, a "duplex" stream is opened. If only
one pointer is passed, an input-only or output-only stream is created.
Duplex streams have the same sample rate, and sample type. They don't have to
have the same number of channels.
`data_callback` now has two pointers to audio buffers: an input buffer (`NULL`
if this is an output-only stream) containing input data (e.g. a microphone), and
an output buffer, to be filled, as usual, with the audio frames to play. The
two buffers always have the exact same number of audio frames, and are
temporally correlated in a way that ensures the minimal loop-back latency on
the system if one directly copies the input buffer to the output buffer.
No functionnal changes are present in this patch, just signature changes.
Asserts have been added to prevent users to try to use the input code path for
now.
Actual implementations with the input code for different platforms will follow.
Green `mozilla-central` push:
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=15b4dd3cbbe8>
2016-01-13 19:16:50 +03:00
|
|
|
memset(outputbuffer, 0, nframes * sizeof(short));
|
2016-06-03 13:17:03 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
total_frames_written += nframes;
|
|
|
|
return nframes;
|
|
|
|
}
|
|
|
|
|
2012-06-06 07:33:12 +04:00
|
|
|
void
|
2016-08-23 04:20:54 +03:00
|
|
|
test_drain_state_callback(cubeb_stream * /*stm*/, void * /*user_ptr*/, cubeb_state state)
|
2011-07-08 08:23:47 +04:00
|
|
|
{
|
|
|
|
if (state == CUBEB_STATE_DRAINED) {
|
|
|
|
assert(!got_drain);
|
|
|
|
got_drain = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
test_drain(void)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
cubeb * ctx;
|
|
|
|
cubeb_stream * stream;
|
|
|
|
cubeb_stream_params params;
|
|
|
|
uint64_t position;
|
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
BEGIN_TEST;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
total_frames_written = 0;
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
r = cubeb_init(&ctx, "test_sanity");
|
|
|
|
assert(r == 0 && ctx);
|
|
|
|
|
2011-08-29 07:56:02 +04:00
|
|
|
params.format = STREAM_FORMAT;
|
|
|
|
params.rate = STREAM_RATE;
|
|
|
|
params.channels = STREAM_CHANNELS;
|
2016-06-09 12:45:25 +03:00
|
|
|
#if defined(__ANDROID__)
|
2016-06-09 13:31:11 +03:00
|
|
|
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
2016-06-09 12:45:25 +03:00
|
|
|
#endif
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2016-01-20 21:17:11 +03:00
|
|
|
r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
|
2011-07-08 08:23:47 +04:00
|
|
|
test_drain_data_callback, test_drain_state_callback, &dummy);
|
|
|
|
assert(r == 0 && stream);
|
|
|
|
|
|
|
|
r = cubeb_stream_start(stream);
|
|
|
|
assert(r == 0);
|
|
|
|
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
do_drain = 1;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
if (got_drain) {
|
|
|
|
break;
|
2014-02-26 22:48:20 +04:00
|
|
|
} else {
|
2014-09-29 04:01:36 +04:00
|
|
|
assert(position <= total_frames_written);
|
2011-07-08 08:23:47 +04:00
|
|
|
}
|
2012-12-05 06:55:34 +04:00
|
|
|
delay(500);
|
2011-07-08 08:23:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
r = cubeb_stream_get_position(stream, &position);
|
|
|
|
assert(r == 0);
|
|
|
|
assert(got_drain);
|
2013-09-02 23:16:49 +04:00
|
|
|
|
2014-09-29 04:01:36 +04:00
|
|
|
// Really, we should be able to rely on position reaching our final written frame, but
|
|
|
|
// for now let's make sure it doesn't continue beyond that point.
|
2014-09-29 04:08:39 +04:00
|
|
|
//assert(position <= total_frames_written);
|
2011-07-08 08:23:47 +04:00
|
|
|
|
|
|
|
cubeb_stream_destroy(stream);
|
|
|
|
cubeb_destroy(ctx);
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2015-11-26 00:57:04 +03:00
|
|
|
END_TEST;
|
|
|
|
}
|
2011-07-08 08:23:47 +04:00
|
|
|
|
2014-04-04 05:57:30 +04:00
|
|
|
int is_windows_7()
|
2012-05-04 05:02:37 +04:00
|
|
|
{
|
2014-09-20 22:35:12 +04:00
|
|
|
#ifdef __MINGW32__
|
2014-11-28 05:56:44 +03:00
|
|
|
printf("Warning: this test was built with MinGW.\n"
|
|
|
|
"MinGW does not contain necessary version checking infrastructure. Claiming to be Windows 7, even if we're not.\n");
|
|
|
|
return 1;
|
2014-09-20 22:35:12 +04:00
|
|
|
#endif
|
|
|
|
#if (defined(_WIN32) || defined(__WIN32__)) && ( !defined(__MINGW32__))
|
2014-11-28 05:56:44 +03:00
|
|
|
OSVERSIONINFOEX osvi;
|
|
|
|
DWORDLONG condition_mask = 0;
|
2014-04-04 05:57:30 +04:00
|
|
|
|
2014-11-28 05:56:44 +03:00
|
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
2014-04-15 04:17:42 +04:00
|
|
|
|
2014-11-28 05:56:44 +03:00
|
|
|
// NT 6.1 is Windows 7
|
|
|
|
osvi.dwMajorVersion = 6;
|
|
|
|
osvi.dwMinorVersion = 1;
|
2014-04-15 04:17:42 +04:00
|
|
|
|
2014-11-28 05:56:44 +03:00
|
|
|
VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, VER_EQUAL);
|
|
|
|
VER_SET_CONDITION(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
2014-04-15 04:17:42 +04:00
|
|
|
|
2014-11-28 05:56:44 +03:00
|
|
|
return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition_mask);
|
2014-04-04 05:57:30 +04:00
|
|
|
#else
|
2014-04-15 04:17:42 +04:00
|
|
|
return 0;
|
2014-04-04 05:57:30 +04:00
|
|
|
#endif
|
2012-05-04 05:02:37 +04:00
|
|
|
}
|
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
int
|
2016-08-23 04:20:54 +03:00
|
|
|
main(int /*argc*/, char * /*argv*/[])
|
2011-07-08 08:23:47 +04:00
|
|
|
{
|
2015-11-26 01:04:12 +03:00
|
|
|
#ifdef CUBEB_GECKO_BUILD
|
|
|
|
ScopedXPCOM xpcom("test_sanity");
|
|
|
|
#endif
|
|
|
|
|
2014-04-04 05:57:30 +04:00
|
|
|
test_init_destroy_context();
|
|
|
|
test_init_destroy_multiple_contexts();
|
2014-10-12 22:51:37 +04:00
|
|
|
test_context_variables();
|
2014-04-04 05:57:30 +04:00
|
|
|
test_init_destroy_stream();
|
|
|
|
test_init_destroy_multiple_streams();
|
2014-10-14 09:21:49 +04:00
|
|
|
test_configure_stream();
|
2014-04-04 05:57:30 +04:00
|
|
|
test_basic_stream_operations();
|
|
|
|
test_stream_position();
|
|
|
|
|
|
|
|
/* Sometimes, when using WASAPI on windows 7 (vista and 8 are okay), and
|
|
|
|
* calling Activate a lot on an AudioClient, 0x800700b7 is returned. This is
|
|
|
|
* the HRESULT value for "Cannot create a file when that file already exists",
|
|
|
|
* and is not documented as a possible return value for this call. Hence, we
|
|
|
|
* try to limit the number of streams we create in this test. */
|
|
|
|
if (!is_windows_7()) {
|
2014-09-17 09:22:06 +04:00
|
|
|
test_init_destroy_multiple_contexts_and_streams();
|
|
|
|
|
2014-04-04 05:57:30 +04:00
|
|
|
delay_callback = 0;
|
|
|
|
test_init_start_stop_destroy_multiple_streams(0, 0);
|
|
|
|
test_init_start_stop_destroy_multiple_streams(1, 0);
|
|
|
|
test_init_start_stop_destroy_multiple_streams(0, 150);
|
|
|
|
test_init_start_stop_destroy_multiple_streams(1, 150);
|
|
|
|
delay_callback = 1;
|
|
|
|
test_init_start_stop_destroy_multiple_streams(0, 0);
|
|
|
|
test_init_start_stop_destroy_multiple_streams(1, 0);
|
|
|
|
test_init_start_stop_destroy_multiple_streams(0, 150);
|
|
|
|
test_init_start_stop_destroy_multiple_streams(1, 150);
|
|
|
|
}
|
2012-05-02 08:53:57 +04:00
|
|
|
delay_callback = 0;
|
2011-07-08 08:23:47 +04:00
|
|
|
test_drain();
|
|
|
|
/*
|
|
|
|
to implement:
|
|
|
|
test_eos_during_prefill();
|
|
|
|
test_stream_destroy_pending_drain();
|
|
|
|
*/
|
2012-05-04 05:02:37 +04:00
|
|
|
printf("\n");
|
2015-11-26 00:57:04 +03:00
|
|
|
|
2011-07-08 08:23:47 +04:00
|
|
|
return 0;
|
|
|
|
}
|