summaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests')
l---------src/tests/Makefile1
-rw-r--r--src/tests/alsa-time-test.c224
-rw-r--r--src/tests/asyncmsgq-test.c105
-rw-r--r--src/tests/asyncq-test.c83
-rw-r--r--src/tests/channelmap-test.c20
-rw-r--r--src/tests/close-test.c20
-rw-r--r--src/tests/connect-stress.c206
-rw-r--r--src/tests/cpulimit-test.c27
-rw-r--r--src/tests/extended-test.c197
-rw-r--r--src/tests/flist-test.c103
-rw-r--r--src/tests/format-test.c106
-rw-r--r--src/tests/get-binary-name-test.c36
-rw-r--r--src/tests/gtk-test.c85
-rw-r--r--src/tests/hook-list-test.c37
-rw-r--r--src/tests/interpol-test.c216
-rw-r--r--src/tests/ipacl-test.c48
-rw-r--r--src/tests/lock-autospawn-test.c109
-rw-r--r--src/tests/mainloop-test.c23
-rw-r--r--src/tests/mcalign-test.c49
-rw-r--r--src/tests/memblock-test.c174
-rw-r--r--src/tests/memblockq-test.c141
-rw-r--r--src/tests/mix-test.c264
-rw-r--r--src/tests/once-test.c111
-rw-r--r--src/tests/pacat-simple.c25
-rw-r--r--src/tests/parec-simple.c22
-rw-r--r--src/tests/prioq-test.c44
-rw-r--r--src/tests/proplist-test.c96
-rw-r--r--src/tests/queue-test.c64
-rw-r--r--src/tests/remix-test.c83
-rw-r--r--src/tests/resampler-test.c487
-rw-r--r--src/tests/rtpoll-test.c85
-rw-r--r--src/tests/rtstutter.c117
-rw-r--r--src/tests/sig2str-test.c37
-rw-r--r--src/tests/sigbus-test.c70
-rw-r--r--src/tests/smoother-test.c82
-rw-r--r--src/tests/stripnul.c70
-rw-r--r--src/tests/strlist-test.c10
-rw-r--r--src/tests/sync-playback.c48
-rw-r--r--src/tests/thread-mainloop-test.c44
-rw-r--r--src/tests/thread-test.c140
-rw-r--r--src/tests/usergroup-test.c155
-rw-r--r--src/tests/utf8-test.c6
-rw-r--r--src/tests/vector-test.c83
-rw-r--r--src/tests/voltest.c120
-rw-r--r--src/tests/volume-ui.py282
45 files changed, 4274 insertions, 281 deletions
diff --git a/src/tests/Makefile b/src/tests/Makefile
deleted file mode 120000
index c110232d..00000000
--- a/src/tests/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../pulse/Makefile \ No newline at end of file
diff --git a/src/tests/alsa-time-test.c b/src/tests/alsa-time-test.c
new file mode 100644
index 00000000..1a572b30
--- /dev/null
+++ b/src/tests/alsa-time-test.c
@@ -0,0 +1,224 @@
+#include <assert.h>
+#include <inttypes.h>
+#include <time.h>
+
+#include <alsa/asoundlib.h>
+
+static uint64_t timespec_us(const struct timespec *ts) {
+ return
+ ts->tv_sec * 1000000LLU +
+ ts->tv_nsec / 1000LLU;
+}
+
+int main(int argc, char *argv[]) {
+ const char *dev;
+ int r, cap;
+ snd_pcm_hw_params_t *hwparams;
+ snd_pcm_sw_params_t *swparams;
+ snd_pcm_status_t *status;
+ snd_pcm_t *pcm;
+ unsigned rate = 44100;
+ unsigned periods = 2;
+ snd_pcm_uframes_t boundary, buffer_size = 44100/10; /* 100s */
+ int dir = 1;
+ struct timespec start, last_timestamp = { 0, 0 };
+ uint64_t start_us;
+ snd_pcm_sframes_t last_avail = 0, last_delay = 0;
+ struct pollfd *pollfds;
+ int n_pollfd;
+ int64_t sample_count = 0;
+
+ snd_pcm_hw_params_alloca(&hwparams);
+ snd_pcm_sw_params_alloca(&swparams);
+ snd_pcm_status_alloca(&status);
+
+ r = clock_gettime(CLOCK_MONOTONIC, &start);
+ assert(r == 0);
+
+ start_us = timespec_us(&start);
+
+ dev = argc > 1 ? argv[1] : "front:AudioPCI";
+ cap = argc > 2 ? atoi(argv[2]) : 0;
+
+ if (cap == 0)
+ r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_PLAYBACK, 0);
+ else
+ r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_CAPTURE, 0);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_any(pcm, hwparams);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_rate_resample(pcm, hwparams, 0);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S16_LE);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, NULL);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_periods_integer(pcm, hwparams);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_periods_near(pcm, hwparams, &periods, &dir);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_set_buffer_size_near(pcm, hwparams, &buffer_size);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params(pcm, hwparams);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_current(pcm, hwparams);
+ assert(r == 0);
+
+ r = snd_pcm_sw_params_current(pcm, swparams);
+ assert(r == 0);
+
+ if (cap == 0)
+ r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 1);
+ else
+ r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 0);
+ assert(r == 0);
+
+ r = snd_pcm_sw_params_set_period_event(pcm, swparams, 0);
+ assert(r == 0);
+
+ r = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+ assert(r == 0);
+ r = snd_pcm_sw_params_set_start_threshold(pcm, swparams, buffer_size);
+ assert(r == 0);
+
+ r = snd_pcm_sw_params_get_boundary(swparams, &boundary);
+ assert(r == 0);
+ r = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary);
+ assert(r == 0);
+
+ r = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE);
+ assert(r == 0);
+
+ r = snd_pcm_sw_params(pcm, swparams);
+ assert(r == 0);
+
+ r = snd_pcm_prepare(pcm);
+ assert(r == 0);
+
+ r = snd_pcm_sw_params_current(pcm, swparams);
+ assert(r == 0);
+
+/* assert(snd_pcm_hw_params_is_monotonic(hwparams) > 0); */
+
+ n_pollfd = snd_pcm_poll_descriptors_count(pcm);
+ assert(n_pollfd > 0);
+
+ pollfds = malloc(sizeof(struct pollfd) * n_pollfd);
+ assert(pollfds);
+
+ r = snd_pcm_poll_descriptors(pcm, pollfds, n_pollfd);
+ assert(r == n_pollfd);
+
+ if (cap) {
+ r = snd_pcm_start(pcm);
+ assert(r == 0);
+ }
+
+ for (;;) {
+ snd_pcm_sframes_t avail, delay;
+ struct timespec now, timestamp;
+ unsigned short revents;
+ int handled = 0;
+ uint64_t now_us, timestamp_us;
+ snd_pcm_state_t state;
+ unsigned long long pos;
+
+ r = poll(pollfds, n_pollfd, 0);
+ assert(r >= 0);
+
+ r = snd_pcm_poll_descriptors_revents(pcm, pollfds, n_pollfd, &revents);
+ assert(r == 0);
+
+ if (cap == 0)
+ assert((revents & ~POLLOUT) == 0);
+ else
+ assert((revents & ~POLLIN) == 0);
+
+ avail = snd_pcm_avail(pcm);
+ assert(avail >= 0);
+
+ r = snd_pcm_status(pcm, status);
+ assert(r == 0);
+
+ /* This assertion fails from time to time. ALSA seems to be broken */
+/* assert(avail == (snd_pcm_sframes_t) snd_pcm_status_get_avail(status)); */
+/* printf("%lu %lu\n", (unsigned long) avail, (unsigned long) snd_pcm_status_get_avail(status)); */
+
+ snd_pcm_status_get_htstamp(status, &timestamp);
+ delay = snd_pcm_status_get_delay(status);
+ state = snd_pcm_status_get_state(status);
+
+ r = clock_gettime(CLOCK_MONOTONIC, &now);
+ assert(r == 0);
+
+ assert(!revents || avail > 0);
+
+ if ((!cap && avail) || (cap && (unsigned)avail >= buffer_size)) {
+ snd_pcm_sframes_t sframes;
+ static const uint16_t psamples[2] = { 0, 0 };
+ uint16_t csamples[2];
+
+ if (cap == 0)
+ sframes = snd_pcm_writei(pcm, psamples, 1);
+ else
+ sframes = snd_pcm_readi(pcm, csamples, 1);
+ assert(sframes == 1);
+
+ handled = 1;
+ sample_count++;
+ }
+
+ if (!handled &&
+ memcmp(&timestamp, &last_timestamp, sizeof(timestamp)) == 0 &&
+ avail == last_avail &&
+ delay == last_delay) {
+ /* This is boring */
+ continue;
+ }
+
+ now_us = timespec_us(&now);
+ timestamp_us = timespec_us(&timestamp);
+
+ if (cap == 0)
+ pos = (unsigned long long) ((sample_count - handled - delay) * 1000000LU / 44100);
+ else
+ pos = (unsigned long long) ((sample_count - handled + delay) * 1000000LU / 44100);
+
+ printf("%llu\t%llu\t%llu\t%llu\t%li\t%li\t%i\t%i\t%i\n",
+ (unsigned long long) (now_us - start_us),
+ (unsigned long long) (timestamp_us ? timestamp_us - start_us : 0),
+ pos,
+ (unsigned long long) sample_count,
+ (signed long) avail,
+ (signed long) delay,
+ revents,
+ handled,
+ state);
+
+ if (cap == 0)
+ /** When this assert is hit, most likely something bad
+ * happened, i.e. the avail jumped suddenly. */
+ assert((unsigned) avail <= buffer_size);
+
+ last_avail = avail;
+ last_delay = delay;
+ last_timestamp = timestamp;
+ }
+
+ return 0;
+}
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
new file mode 100644
index 00000000..96e5a0df
--- /dev/null
+++ b/src/tests/asyncmsgq-test.c
@@ -0,0 +1,105 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulsecore/asyncmsgq.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+
+enum {
+ OPERATION_A,
+ OPERATION_B,
+ OPERATION_C,
+ QUIT
+};
+
+static void the_thread(void *_q) {
+ pa_asyncmsgq *q = _q;
+ int quit = 0;
+
+ do {
+ int code = 0;
+
+ pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, NULL, 1) == 0);
+
+ switch (code) {
+
+ case OPERATION_A:
+ printf("Operation A\n");
+ break;
+
+ case OPERATION_B:
+ printf("Operation B\n");
+ break;
+
+ case OPERATION_C:
+ printf("Operation C\n");
+ break;
+
+ case QUIT:
+ printf("quit\n");
+ quit = 1;
+ break;
+ }
+
+ pa_asyncmsgq_done(q, 0);
+
+ } while (!quit);
+}
+
+int main(int argc, char *argv[]) {
+ pa_asyncmsgq *q;
+ pa_thread *t;
+
+ pa_assert_se(q = pa_asyncmsgq_new(0));
+
+ pa_assert_se(t = pa_thread_new("test", the_thread, q));
+
+ printf("Operation A post\n");
+ pa_asyncmsgq_post(q, NULL, OPERATION_A, NULL, 0, NULL, NULL);
+
+ pa_thread_yield();
+
+ printf("Operation B post\n");
+ pa_asyncmsgq_post(q, NULL, OPERATION_B, NULL, 0, NULL, NULL);
+
+ pa_thread_yield();
+
+ printf("Operation C send\n");
+ pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL, 0, NULL);
+
+ pa_thread_yield();
+
+ printf("Quit post\n");
+ pa_asyncmsgq_post(q, NULL, QUIT, NULL, 0, NULL, NULL);
+
+ pa_thread_free(t);
+
+ pa_asyncmsgq_unref(q);
+
+ return 0;
+}
diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
new file mode 100644
index 00000000..46bac9f4
--- /dev/null
+++ b/src/tests/asyncq-test.c
@@ -0,0 +1,83 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulse/util.h>
+#include <pulsecore/asyncq.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+
+static void producer(void *_q) {
+ pa_asyncq *q = _q;
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ printf("pushing %i\n", i);
+ pa_asyncq_push(q, PA_UINT_TO_PTR(i+1), 1);
+ }
+
+ pa_asyncq_push(q, PA_UINT_TO_PTR(-1), TRUE);
+ printf("pushed end\n");
+}
+
+static void consumer(void *_q) {
+ pa_asyncq *q = _q;
+ void *p;
+ int i;
+
+ pa_msleep(1000);
+
+ for (i = 0;; i++) {
+ p = pa_asyncq_pop(q, TRUE);
+
+ if (p == PA_UINT_TO_PTR(-1))
+ break;
+
+ pa_assert(p == PA_UINT_TO_PTR(i+1));
+
+ printf("popped %i\n", i);
+ }
+
+ printf("popped end\n");
+}
+
+int main(int argc, char *argv[]) {
+ pa_asyncq *q;
+ pa_thread *t1, *t2;
+
+ pa_assert_se(q = pa_asyncq_new(0));
+
+ pa_assert_se(t1 = pa_thread_new("producer", producer, q));
+ pa_assert_se(t2 = pa_thread_new("consumer", consumer, q));
+
+ pa_thread_free(t1);
+ pa_thread_free(t2);
+
+ pa_asyncq_free(q, NULL);
+
+ return 0;
+}
diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c
index 124ce576..70d6a6a9 100644
--- a/src/tests/channelmap-test.c
+++ b/src/tests/channelmap-test.c
@@ -1,33 +1,37 @@
-/* $Id$ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <stdio.h>
#include <assert.h>
#include <pulse/channelmap.h>
-#include <pulsecore/gccmacro.h>
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
+int main(int argc, char *argv[]) {
char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_channel_map map, map2;
pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AIFF);
-
+
fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AUX);
-
+
fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_ALSA);
-
+
fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
-
+
+ pa_channel_map_init_extend(&map, 14, PA_CHANNEL_MAP_ALSA);
+
+ fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
+
pa_channel_map_parse(&map2, cm);
assert(pa_channel_map_equal(&map, &map2));
pa_channel_map_parse(&map2, "left,test");
-
return 0;
}
diff --git a/src/tests/close-test.c b/src/tests/close-test.c
new file mode 100644
index 00000000..7a6fec57
--- /dev/null
+++ b/src/tests/close-test.c
@@ -0,0 +1,20 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <pulsecore/core-util.h>
+
+int main(int argc, char *argv[]) {
+
+ open("/dev/null", O_RDONLY);
+ open("/dev/null", O_RDONLY);
+ open("/dev/null", O_RDONLY);
+ open("/dev/null", O_RDONLY);
+
+ pa_close_all(5, -1);
+
+ return 0;
+}
diff --git a/src/tests/connect-stress.c b/src/tests/connect-stress.c
new file mode 100644
index 00000000..eadcf885
--- /dev/null
+++ b/src/tests/connect-stress.c
@@ -0,0 +1,206 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <pulse/pulseaudio.h>
+#include <pulse/mainloop.h>
+
+#include <pulsecore/sink.h>
+
+/* Set the number of streams such that it allows two simultaneous instances of
+ * connect-stress to be run and not go above the max limit for streams-per-sink.
+ * This leaves enough room for a couple other streams from regular system usage,
+ * which makes a non-error abort less likely (although still easily possible of
+ * playing >=3 streams outside of the test - including internal loopback, rtp,
+ * combine, remap streams etc.) */
+#define NSTREAMS ((PA_MAX_INPUTS_PER_SINK/2) - 1)
+#define NTESTS 1000
+#define SAMPLE_HZ 44100
+
+static pa_context *context = NULL;
+static pa_stream *streams[NSTREAMS];
+static pa_threaded_mainloop *mainloop = NULL;
+
+static const pa_sample_spec sample_spec = {
+ .format = PA_SAMPLE_FLOAT32,
+ .rate = SAMPLE_HZ,
+ .channels = 1
+};
+
+static void context_state_callback(pa_context *c, void *userdata);
+
+static void connect(const char *name, int *try) {
+ int ret;
+ pa_mainloop_api *api;
+
+ /* Set up a new main loop */
+ mainloop = pa_threaded_mainloop_new();
+ assert(mainloop);
+
+ api = pa_threaded_mainloop_get_api(mainloop);
+ context = pa_context_new(api, name);
+ assert(context);
+
+ pa_context_set_state_callback(context, context_state_callback, try);
+
+ /* Connect the context */
+ if (pa_context_connect(context, NULL, 0, NULL) < 0) {
+ fprintf(stderr, "pa_context_connect() failed.\n");
+ abort();
+ }
+
+ ret = pa_threaded_mainloop_start(mainloop);
+ assert(ret == 0);
+}
+
+static void disconnect(void) {
+ int i;
+
+ assert(mainloop);
+ assert(context);
+
+ pa_threaded_mainloop_lock(mainloop);
+
+ for (i = 0; i < NSTREAMS; i++)
+ if (streams[i]) {
+ pa_stream_disconnect(streams[i]);
+ pa_stream_unref(streams[i]);
+ streams[i] = NULL;
+ }
+
+ pa_context_disconnect(context);
+ context = NULL;
+
+ pa_threaded_mainloop_unlock(mainloop);
+ pa_threaded_mainloop_stop(mainloop);
+ pa_threaded_mainloop_free(mainloop);
+ mainloop = NULL;
+}
+
+static const pa_buffer_attr buffer_attr = {
+ .maxlength = SAMPLE_HZ * sizeof(float) * NSTREAMS,
+ .tlength = (uint32_t) -1,
+ .prebuf = 0, /* Setting prebuf to 0 guarantees us the the streams will run synchronously, no matter what */
+ .minreq = (uint32_t) -1,
+ .fragsize = 0
+};
+
+static void stream_write_callback(pa_stream *stream, size_t nbytes, void *userdata) {
+ char silence[8192];
+
+ memset(silence, 0, sizeof(silence));
+
+ while (nbytes) {
+ int n = PA_MIN(sizeof(silence), nbytes);
+ pa_stream_write(stream, silence, n, NULL, 0, 0);
+ nbytes -= n;
+ }
+}
+
+static void stream_state_callback(pa_stream *s, void *userdata) {
+ assert(s);
+
+ switch (pa_stream_get_state(s)) {
+ case PA_STREAM_UNCONNECTED:
+ case PA_STREAM_CREATING:
+ case PA_STREAM_TERMINATED:
+ case PA_STREAM_READY:
+ break;
+
+ default:
+ case PA_STREAM_FAILED:
+ fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ abort();
+ }
+}
+
+static void context_state_callback(pa_context *c, void *userdata) {
+ int *try;
+
+ assert(c);
+ assert(userdata);
+
+ try = (int*)userdata;
+
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY: {
+
+ int i;
+ fprintf(stderr, "Connection (%d of %d) established.\n", (*try)+1, NTESTS);
+
+ for (i = 0; i < NSTREAMS; i++) {
+ char name[64];
+
+ snprintf(name, sizeof(name), "stream #%i", i);
+ streams[i] = pa_stream_new(c, name, &sample_spec, NULL);
+ assert(streams[i]);
+ pa_stream_set_state_callback(streams[i], stream_state_callback, NULL);
+ pa_stream_set_write_callback(streams[i], stream_write_callback, NULL);
+ pa_stream_connect_playback(streams[i], NULL, &buffer_attr, 0, NULL, NULL);
+ }
+
+ break;
+ }
+
+ case PA_CONTEXT_TERMINATED:
+ fprintf(stderr, "Connection terminated.\n");
+ pa_context_unref(context);
+ context = NULL;
+ break;
+
+ case PA_CONTEXT_FAILED:
+ default:
+ fprintf(stderr, "Context error: %s\n", pa_strerror(pa_context_errno(c)));
+ abort();
+ }
+}
+
+int main(int argc, char *argv[]) {
+ int i;
+
+ for (i = 0; i < NSTREAMS; i++)
+ streams[i] = NULL;
+
+ for (i = 0; i < NTESTS; i++) {
+ connect(argv[0], &i);
+ usleep(rand() % 500000);
+ disconnect();
+ usleep(rand() % 500000);
+ }
+
+ fprintf(stderr, "Done.\n");
+
+ return 0;
+}
diff --git a/src/tests/cpulimit-test.c b/src/tests/cpulimit-test.c
index 2302a26d..8bd03417 100644
--- a/src/tests/cpulimit-test.c
+++ b/src/tests/cpulimit-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2 of the
+ published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -24,19 +22,18 @@
#endif
#include <assert.h>
-#include <sys/time.h>
+#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <pulse/mainloop.h>
-#include <pulsecore/gccmacro.h>
#ifdef TEST2
#include <pulse/mainloop-signal.h>
#endif
-#include "../daemon/cpulimit.h"
+#include <daemon/cpulimit.h>
/* A simple example for testing the cpulimit subsystem */
@@ -44,10 +41,10 @@ static time_t start;
#ifdef TEST2
-static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UNUSED int sig, PA_GCC_UNUSED void *userdata) {
+static void func(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
time_t now;
time(&now);
-
+
if ((now - start) >= 30) {
m->quit(m, 1);
fprintf(stderr, "Test failed\n");
@@ -57,9 +54,9 @@ static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UN
#endif
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
+int main(int argc, char *argv[]) {
pa_mainloop *m;
-
+
m = pa_mainloop_new();
assert(m);
@@ -77,7 +74,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
for (;;) {
time_t now;
time(&now);
-
+
if ((now - start) >= 30) {
fprintf(stderr, "Test failed\n");
break;
@@ -86,7 +83,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
#endif
pa_cpu_limit_done();
-
+
pa_mainloop_free(m);
return 0;
diff --git a/src/tests/extended-test.c b/src/tests/extended-test.c
new file mode 100644
index 00000000..631fdc89
--- /dev/null
+++ b/src/tests/extended-test.c
@@ -0,0 +1,197 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <pulse/pulseaudio.h>
+#include <pulse/mainloop.h>
+
+#define NSTREAMS 4
+#define SINE_HZ 440
+#define SAMPLE_HZ 8000
+
+static pa_context *context = NULL;
+static pa_stream *streams[NSTREAMS];
+static pa_mainloop_api *mainloop_api = NULL;
+
+static float data[SAMPLE_HZ]; /* one second space */
+
+static int n_streams_ready = 0;
+
+static const pa_buffer_attr buffer_attr = {
+ .maxlength = SAMPLE_HZ*sizeof(float)*NSTREAMS, /* exactly space for the entire play time */
+ .tlength = (uint32_t) -1,
+ .prebuf = 0, /* Setting prebuf to 0 guarantees us the the streams will run synchronously, no matter what */
+ .minreq = (uint32_t) -1,
+ .fragsize = 0
+};
+
+static void nop_free_cb(void *p) {}
+
+static void underflow_cb(struct pa_stream *s, void *userdata) {
+ int i = (int) (long) userdata;
+
+ fprintf(stderr, "Stream %i finished\n", i);
+
+ if (++n_streams_ready >= 2*NSTREAMS) {
+ fprintf(stderr, "We're done\n");
+ mainloop_api->quit(mainloop_api, 0);
+ }
+}
+
+/* This routine is called whenever the stream state changes */
+static void stream_state_callback(pa_stream *s, void *userdata) {
+ assert(s);
+
+ switch (pa_stream_get_state(s)) {
+ case PA_STREAM_UNCONNECTED:
+ case PA_STREAM_CREATING:
+ case PA_STREAM_TERMINATED:
+ break;
+
+ case PA_STREAM_READY: {
+
+ int r, i = (int) (long) userdata;
+
+ fprintf(stderr, "Writing data to stream %i.\n", i);
+
+ r = pa_stream_write(s, data, sizeof(data), nop_free_cb, (int64_t) sizeof(data) * (int64_t) i, PA_SEEK_ABSOLUTE);
+ assert(r == 0);
+
+ /* Be notified when this stream is drained */
+ pa_stream_set_underflow_callback(s, underflow_cb, userdata);
+
+ /* All streams have been set up, let's go! */
+ if (++n_streams_ready >= NSTREAMS) {
+ fprintf(stderr, "Uncorking\n");
+ pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL));
+ }
+
+ break;
+ }
+
+ default:
+ case PA_STREAM_FAILED:
+ fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ abort();
+ }
+}
+
+/* This is called whenever the context status changes */
+static void context_state_callback(pa_context *c, void *userdata) {
+ assert(c);
+
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY: {
+
+ int i;
+ fprintf(stderr, "Connection established.\n");
+
+ for (i = 0; i < NSTREAMS; i++) {
+ char name[64];
+ pa_format_info *formats[1];
+
+ formats[0] = pa_format_info_new();
+ formats[0]->encoding = PA_ENCODING_PCM;
+ pa_format_info_set_sample_format(formats[0], PA_SAMPLE_FLOAT32);
+ pa_format_info_set_rate(formats[0], SAMPLE_HZ);
+ pa_format_info_set_channels(formats[0], 1);
+
+ fprintf(stderr, "Creating stream %i\n", i);
+
+ snprintf(name, sizeof(name), "stream #%i", i);
+
+ streams[i] = pa_stream_new_extended(c, name, formats, 1, NULL);
+ assert(streams[i]);
+ pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i);
+ pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]);
+
+ pa_format_info_free(formats[0]);
+ }
+
+ break;
+ }
+
+ case PA_CONTEXT_TERMINATED:
+ mainloop_api->quit(mainloop_api, 0);
+ break;
+
+ case PA_CONTEXT_FAILED:
+ default:
+ fprintf(stderr, "Context error: %s\n", pa_strerror(pa_context_errno(c)));
+ abort();
+ }
+}
+
+int main(int argc, char *argv[]) {
+ pa_mainloop* m = NULL;
+ int i, ret = 0;
+
+ for (i = 0; i < SAMPLE_HZ; i++)
+ data[i] = (float) sin(((double) i/SAMPLE_HZ)*2*M_PI*SINE_HZ)/2;
+
+ for (i = 0; i < NSTREAMS; i++)
+ streams[i] = NULL;
+
+ /* Set up a new main loop */
+ m = pa_mainloop_new();
+ assert(m);
+
+ mainloop_api = pa_mainloop_get_api(m);
+
+ context = pa_context_new(mainloop_api, argv[0]);
+ assert(context);
+
+ pa_context_set_state_callback(context, context_state_callback, NULL);
+
+ /* Connect the context */
+ if (pa_context_connect(context, NULL, 0, NULL) < 0) {
+ fprintf(stderr, "pa_context_connect() failed.\n");
+ goto quit;
+ }
+
+ if (pa_mainloop_run(m, &ret) < 0)
+ fprintf(stderr, "pa_mainloop_run() failed.\n");
+
+quit:
+ pa_context_unref(context);
+
+ for (i = 0; i < NSTREAMS; i++)
+ if (streams[i])
+ pa_stream_unref(streams[i]);
+
+ pa_mainloop_free(m);
+
+ return ret;
+}
diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c
new file mode 100644
index 00000000..69152041
--- /dev/null
+++ b/src/tests/flist-test.c
@@ -0,0 +1,103 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulse/util.h>
+#include <pulse/xmalloc.h>
+#include <pulsecore/flist.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+
+#define THREADS_MAX 20
+
+static pa_flist *flist;
+static int quit = 0;
+
+static void spin(void) {
+ int k;
+
+ /* Spin a little */
+ k = rand() % 10000;
+ for (; k > 0; k--)
+ pa_thread_yield();
+}
+
+static void thread_func(void *data) {
+ char *s = data;
+ int n = 0;
+ int b = 1;
+
+ while (!quit) {
+ char *text;
+
+ /* Allocate some memory, if possible take it from the flist */
+ if (b && (text = pa_flist_pop(flist)))
+ pa_log("%s: popped '%s'", s, text);
+ else {
+ text = pa_sprintf_malloc("Block %i, allocated by %s", n++, s);
+ pa_log("%s: allocated '%s'", s, text);
+ }
+
+ b = !b;
+
+ spin();
+
+ /* Give it back to the flist if possible */
+ if (pa_flist_push(flist, text) < 0) {
+ pa_log("%s: failed to push back '%s'", s, text);
+ pa_xfree(text);
+ } else
+ pa_log("%s: pushed", s);
+
+ spin();
+ }
+
+ if (pa_flist_push(flist, s) < 0)
+ pa_xfree(s);
+}
+
+int main(int argc, char* argv[]) {
+ pa_thread *threads[THREADS_MAX];
+ int i;
+
+ flist = pa_flist_new(0);
+
+ for (i = 0; i < THREADS_MAX; i++) {
+ threads[i] = pa_thread_new("test", thread_func, pa_sprintf_malloc("Thread #%i", i+1));
+ assert(threads[i]);
+ }
+
+ pa_msleep(60000);
+ quit = 1;
+
+ for (i = 0; i < THREADS_MAX; i++)
+ pa_thread_free(threads[i]);
+
+ pa_flist_free(flist, pa_xfree);
+
+ return 0;
+}
diff --git a/src/tests/format-test.c b/src/tests/format-test.c
new file mode 100644
index 00000000..888db8c9
--- /dev/null
+++ b/src/tests/format-test.c
@@ -0,0 +1,106 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <pulsecore/macro.h>
+#include <pulse/format.h>
+
+#define INIT(f) f = pa_format_info_new()
+#define DEINIT(f) pa_format_info_free(f);
+#define REINIT(f) { DEINIT(f); INIT(f); }
+
+int main(int argc, char *argv[]) {
+ pa_format_info *f1 = NULL, *f2 = NULL;
+ int rates1[] = { 32000, 44100, 48000 };
+ const char *strings[] = { "thing1", "thing2", "thing3" };
+
+ /* 1. Simple fixed format int check */
+ INIT(f1); INIT(f2);
+ f1->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int(f1, PA_PROP_FORMAT_RATE, 32000);
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 44100);
+ pa_assert(!pa_format_info_is_compatible(f1, f2));
+
+ /* 2. Check int array membership - positive */
+ REINIT(f1); REINIT(f2);
+ f1->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int_array(f1, PA_PROP_FORMAT_RATE, rates1, PA_ELEMENTSOF(rates1));
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 44100);
+ pa_assert(pa_format_info_is_compatible(f1, f2));
+ pa_assert(pa_format_info_is_compatible(f2, f1));
+
+ /* 3. Check int array memebership - negative */
+ REINIT(f2);
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 96000);
+ pa_assert(!pa_format_info_is_compatible(f1, f2));
+ pa_assert(!pa_format_info_is_compatible(f2, f1));
+
+ /* 4. Check int range - positive */
+ REINIT(f1); REINIT(f2);
+ f1->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int_range(f1, PA_PROP_FORMAT_RATE, 32000, 48000);
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 44100);
+ pa_assert(pa_format_info_is_compatible(f1, f2));
+ pa_assert(pa_format_info_is_compatible(f2, f1));
+
+ /* 5. Check int range - negative */
+ REINIT(f2);
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 96000);
+ pa_assert(!pa_format_info_is_compatible(f1, f2));
+ pa_assert(!pa_format_info_is_compatible(f2, f1));
+
+ /* 6. Simple fixed format string check */
+ REINIT(f1); REINIT(f2);
+ f1->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_string(f1, "format.test_string", "thing1");
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_string(f2, "format.test_string", "notthing1");
+ pa_assert(!pa_format_info_is_compatible(f1, f2));
+
+ /* 7. Check string array membership - positive */
+ REINIT(f1); REINIT(f2);
+ f1->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_string_array(f1, "format.test_string", strings, PA_ELEMENTSOF(strings));
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_string(f2, "format.test_string", "thing3");
+ pa_assert(pa_format_info_is_compatible(f1, f2));
+ pa_assert(pa_format_info_is_compatible(f2, f1));
+
+ /* 8. Check string array memebership - negative */
+ REINIT(f2);
+ f2->encoding = PA_ENCODING_AC3_IEC61937;
+ pa_format_info_set_prop_string(f2, "format.test_string", "thing5");
+ pa_assert(!pa_format_info_is_compatible(f1, f2));
+ pa_assert(!pa_format_info_is_compatible(f2, f1));
+
+ DEINIT(f1);
+ DEINIT(f2);
+
+ return 0;
+}
diff --git a/src/tests/get-binary-name-test.c b/src/tests/get-binary-name-test.c
index 0cea2b6d..4afe81b3 100644
--- a/src/tests/get-binary-name-test.c
+++ b/src/tests/get-binary-name-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -23,14 +21,34 @@
#include <config.h>
#endif
-#include <limits.h>
#include <stdio.h>
+#include <string.h>
#include <pulse/util.h>
+#include <pulse/xmalloc.h>
int main(int argc, char *argv[]) {
- char exename[PATH_MAX];
+ char *exename;
+ size_t allocated = 128;
+
+ for (;;) {
+ exename = pa_xmalloc(allocated);
+
+ if (!pa_get_binary_name(exename, allocated)) {
+ printf("failed to read binary name\n");
+ pa_xfree(exename);
+ break;
+ }
+
+ if (strlen(exename) < allocated - 1) {
+ printf("%s\n", exename);
+ pa_xfree(exename);
+ break;
+ }
+
+ pa_xfree(exename);
+ allocated *= 2;
+ }
- printf("%s\n", pa_get_binary_name(exename, sizeof(exename)));
return 0;
}
diff --git a/src/tests/gtk-test.c b/src/tests/gtk-test.c
new file mode 100644
index 00000000..6470e484
--- /dev/null
+++ b/src/tests/gtk-test.c
@@ -0,0 +1,85 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib.h>
+
+#include <pulse/context.h>
+#include <pulse/glib-mainloop.h>
+
+pa_context *ctxt;
+pa_glib_mainloop *m;
+
+static void context_state_callback(pa_context *c, void *userdata);
+
+static void connect(void) {
+ int r;
+
+ ctxt = pa_context_new(pa_glib_mainloop_get_api(m), NULL);
+ g_assert(ctxt);
+
+ r = pa_context_connect(ctxt, NULL, PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL, NULL);
+ g_assert(r == 0);
+
+ pa_context_set_state_callback(ctxt, context_state_callback, NULL);
+}
+
+static void context_state_callback(pa_context *c, void *userdata) {
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_FAILED:
+ pa_context_unref(ctxt);
+ ctxt = NULL;
+ connect();
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int argc, char *argv[]) {
+
+ GtkWidget *window;
+
+ gtk_init(&argc, &argv);
+
+ g_set_application_name("This is a test");
+ gtk_window_set_default_icon_name("foobar");
+ g_setenv("PULSE_PROP_media.role", "phone", TRUE);
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW (window), g_get_application_name());
+ gtk_widget_show_all(window);
+
+ m = pa_glib_mainloop_new(NULL);
+ g_assert(m);
+
+ connect();
+ gtk_main();
+
+ pa_context_unref(ctxt);
+ pa_glib_mainloop_free(m);
+
+ return 0;
+}
diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c
new file mode 100644
index 00000000..452e4776
--- /dev/null
+++ b/src/tests/hook-list-test.c
@@ -0,0 +1,37 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/hook-list.h>
+#include <pulsecore/log.h>
+
+static pa_hook_result_t func1(const char *hook_data, const char *call_data, const char *slot_data) {
+ pa_log("(func1) hook=%s call=%s slot=%s", hook_data, call_data, slot_data);
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t func2(const char *hook_data, const char *call_data, const char *slot_data) {
+ pa_log("(func2) hook=%s call=%s slot=%s", hook_data, call_data, slot_data);
+ return PA_HOOK_OK;
+}
+
+int main(int argc, char *argv[]) {
+ pa_hook hook;
+ pa_hook_slot *slot;
+
+ pa_hook_init(&hook, (void*) "hook");
+
+ pa_hook_connect(&hook, PA_HOOK_LATE, (pa_hook_cb_t) func1, (void*) "slot1");
+ slot = pa_hook_connect(&hook, PA_HOOK_NORMAL, (pa_hook_cb_t) func2, (void*) "slot2");
+ pa_hook_connect(&hook, PA_HOOK_NORMAL, (pa_hook_cb_t) func1, (void*) "slot3");
+
+ pa_hook_fire(&hook, (void*) "call1");
+
+ pa_hook_slot_free(slot);
+
+ pa_hook_fire(&hook, (void*) "call2");
+
+ pa_hook_done(&hook);
+
+ return 0;
+}
diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c
index 2df65a45..ffe4ab38 100644
--- a/src/tests/interpol-test.c
+++ b/src/tests/interpol-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -30,24 +28,61 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
-#include <getopt.h>
-#include <math.h>
-
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
#include <pulse/pulseaudio.h>
#include <pulse/mainloop.h>
+#include <pulsecore/thread.h>
+
+#define INTERPOLATE
+//#define CORK
+
static pa_context *context = NULL;
static pa_stream *stream = NULL;
static pa_mainloop_api *mainloop_api = NULL;
+static pa_bool_t playback = TRUE;
+static pa_usec_t latency = 0;
-static void stream_write_cb(pa_stream *p, size_t length, void *userdata) {
-
+static void stream_write_cb(pa_stream *p, size_t nbytes, void *userdata) {
/* Just some silence */
- pa_stream_write(p, pa_xmalloc0(length), length, pa_xfree, 0, PA_SEEK_RELATIVE);
+
+ for (;;) {
+ void *data;
+
+ pa_assert_se((nbytes = pa_stream_writable_size(p)) != (size_t) -1);
+
+ if (nbytes <= 0)
+ break;
+
+ pa_assert_se(pa_stream_begin_write(p, &data, &nbytes) == 0);
+ pa_memzero(data, nbytes);
+ pa_assert_se(pa_stream_write(p, data, nbytes, NULL, 0, PA_SEEK_RELATIVE) == 0);
+ }
+}
+
+static void stream_read_cb(pa_stream *p, size_t nbytes, void *userdata) {
+ /* We don't care about the data, just drop it */
+
+ for (;;) {
+ const void *data;
+
+ pa_assert_se((nbytes = pa_stream_readable_size(p)) != (size_t) -1);
+
+ if (nbytes <= 0)
+ break;
+
+ pa_assert_se(pa_stream_peek(p, &data, &nbytes) == 0);
+ pa_assert_se(pa_stream_drop(p) == 0);
+ }
+}
+
+static void stream_latency_cb(pa_stream *p, void *userdata) {
+#ifndef INTERPOLATE
+ pa_operation *o;
+
+ o = pa_stream_update_timing_info(p, NULL, NULL);
+ pa_operation_unref(o);
+#endif
}
/* This is called whenever the context status changes */
@@ -59,26 +94,47 @@ static void context_state_callback(pa_context *c, void *userdata) {
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
-
- case PA_CONTEXT_READY: {
+ case PA_CONTEXT_READY: {
+ pa_stream_flags_t flags = PA_STREAM_AUTO_TIMING_UPDATE;
+ pa_buffer_attr attr;
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
- .channels = 1
+ .channels = 2
};
-
+
+ pa_zero(attr);
+ attr.maxlength = (uint32_t) -1;
+ attr.tlength = latency > 0 ? (uint32_t) pa_usec_to_bytes(latency, &ss) : (uint32_t) -1;
+ attr.prebuf = (uint32_t) -1;
+ attr.minreq = (uint32_t) -1;
+ attr.fragsize = (uint32_t) -1;
+
+#ifdef INTERPOLATE
+ flags |= PA_STREAM_INTERPOLATE_TIMING;
+#endif
+
+ if (latency > 0)
+ flags |= PA_STREAM_ADJUST_LATENCY;
+
fprintf(stderr, "Connection established.\n");
- stream = pa_stream_new(c, "interpol-test", &ss, NULL);
- assert(stream);
-
- pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
- pa_stream_set_write_callback(stream, stream_write_cb, NULL);
-
+ pa_assert_se(stream = pa_stream_new(c, "interpol-test", &ss, NULL));
+
+ if (playback) {
+ pa_assert_se(pa_stream_connect_playback(stream, NULL, &attr, flags, NULL, NULL) == 0);
+ pa_stream_set_write_callback(stream, stream_write_cb, NULL);
+ } else {
+ pa_assert_se(pa_stream_connect_record(stream, NULL, &attr, flags) == 0);
+ pa_stream_set_read_callback(stream, stream_read_cb, NULL);
+ }
+
+ pa_stream_set_latency_update_callback(stream, stream_latency_cb, NULL);
+
break;
}
-
+
case PA_CONTEXT_TERMINATED:
break;
@@ -91,70 +147,108 @@ static void context_state_callback(pa_context *c, void *userdata) {
int main(int argc, char *argv[]) {
pa_threaded_mainloop* m = NULL;
- int k, r;
+ int k;
struct timeval start, last_info = { 0, 0 };
pa_usec_t old_t = 0, old_rtc = 0;
+#ifdef CORK
+ pa_bool_t corked = FALSE;
+#endif
- /* Set up a new main loop */
- m = pa_threaded_mainloop_new();
- assert(m);
+ pa_log_set_level(PA_LOG_DEBUG);
- mainloop_api = pa_threaded_mainloop_get_api(m);
+ playback = argc <= 1 || !pa_streq(argv[1], "-r");
- context = pa_context_new(mainloop_api, argv[0]);
- assert(context);
+ latency =
+ (argc >= 2 && !pa_streq(argv[1], "-r")) ? atoi(argv[1]) :
+ (argc >= 3 ? atoi(argv[2]) : 0);
+
+ /* Set up a new main loop */
+ pa_assert_se(m = pa_threaded_mainloop_new());
+ pa_assert_se(mainloop_api = pa_threaded_mainloop_get_api(m));
+ pa_assert_se(context = pa_context_new(mainloop_api, argv[0]));
pa_context_set_state_callback(context, context_state_callback, NULL);
- r = pa_context_connect(context, NULL, 0, NULL);
- assert(r >= 0);
+ pa_assert_se(pa_context_connect(context, NULL, 0, NULL) >= 0);
pa_gettimeofday(&start);
-
- pa_threaded_mainloop_start(m);
- for (k = 0; k < 5000; k++) {
- int success = 0, changed = 0;
- pa_usec_t t, rtc;
+ pa_assert_se(pa_threaded_mainloop_start(m) >= 0);
+
+/* #ifdef CORK */
+ for (k = 0; k < 20000; k++)
+/* #else */
+/* for (k = 0; k < 2000; k++) */
+/* #endif */
+ {
+ pa_bool_t success = FALSE, changed = FALSE;
+ pa_usec_t t, rtc, d;
struct timeval now, tv;
-
+ pa_bool_t playing = FALSE;
+
pa_threaded_mainloop_lock(m);
if (stream) {
const pa_timing_info *info;
-
- if (pa_stream_get_time(stream, &t) >= 0)
- success = 1;
- if ((info = pa_stream_get_timing_info(stream)))
- if (last_info.tv_usec != info->timestamp.tv_usec || last_info.tv_sec != info->timestamp.tv_sec) {
- changed = 1;
+ if (pa_stream_get_time(stream, &t) >= 0 &&
+ pa_stream_get_latency(stream, &d, NULL) >= 0)
+ success = TRUE;
+
+ if ((info = pa_stream_get_timing_info(stream))) {
+ if (memcmp(&last_info, &info->timestamp, sizeof(struct timeval))) {
+ changed = TRUE;
last_info = info->timestamp;
}
+ if (info->playing)
+ playing = TRUE;
+ }
}
-
+
pa_threaded_mainloop_unlock(m);
-
- if (success) {
- pa_gettimeofday(&now);
+ pa_gettimeofday(&now);
+
+ if (success) {
+#ifdef CORK
+ pa_bool_t cork_now;
+#endif
rtc = pa_timeval_diff(&now, &start);
- printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, rtc, t, rtc-old_rtc, t-old_t, changed);
+ printf("%i\t%llu\t%llu\t%llu\t%llu\t%lli\t%u\t%u\t%llu\t%llu\n", k,
+ (unsigned long long) rtc,
+ (unsigned long long) t,
+ (unsigned long long) (rtc-old_rtc),
+ (unsigned long long) (t-old_t),
+ (signed long long) rtc - (signed long long) t,
+ changed,
+ playing,
+ (unsigned long long) latency,
+ (unsigned long long) d);
+
+ fflush(stdout);
old_t = t;
old_rtc = rtc;
+
+#ifdef CORK
+ cork_now = (rtc / (2*PA_USEC_PER_SEC)) % 2 == 1;
+
+ if (corked != cork_now) {
+ pa_threaded_mainloop_lock(m);
+ pa_operation_unref(pa_stream_cork(stream, cork_now, NULL, NULL));
+ pa_threaded_mainloop_unlock(m);
+
+ pa_log(cork_now ? "Corking" : "Uncorking");
+
+ corked = cork_now;
+ }
+#endif
}
/* Spin loop, ugly but normal usleep() is just too badly grained */
tv = now;
while (pa_timeval_diff(pa_gettimeofday(&now), &tv) < 1000)
-#ifdef HAVE_PTHREAD_YIELD
- pthread_yield();
-#elif defined(OS_IS_WIN32)
- Sleep(0);
-#else
- ;
-#endif
+ pa_thread_yield();
}
if (m)
@@ -164,7 +258,7 @@ int main(int argc, char *argv[]) {
pa_stream_disconnect(stream);
pa_stream_unref(stream);
}
-
+
if (context) {
pa_context_disconnect(context);
pa_context_unref(context);
@@ -172,6 +266,6 @@ int main(int argc, char *argv[]) {
if (m)
pa_threaded_mainloop_free(m);
-
+
return 0;
}
diff --git a/src/tests/ipacl-test.c b/src/tests/ipacl-test.c
index b98151ee..be9caadf 100644
--- a/src/tests/ipacl-test.c
+++ b/src/tests/ipacl-test.c
@@ -1,30 +1,44 @@
-/* $Id$ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
+#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
-#include <arpa/inet.h>
#include <assert.h>
#include <string.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#include <pulsecore/socket.h>
+#include <pulsecore/macro.h>
#include <pulsecore/ipacl.h>
+#include <pulsecore/arpa-inet.h>
int main(int argc, char *argv[]) {
struct sockaddr_in sa;
+#ifdef HAVE_IPV6
struct sockaddr_in6 sa6;
+#endif
int fd;
int r;
pa_ip_acl *acl;
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket(PF_INET, SOCK_STREAM, 0);
assert(fd >= 0);
-
+
sa.sin_family = AF_INET;
sa.sin_port = htons(22);
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
-
+
r = connect(fd, (struct sockaddr*) &sa, sizeof(sa));
assert(r >= 0);
@@ -47,7 +61,7 @@ int main(int argc, char *argv[]) {
assert(acl);
printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
pa_ip_acl_free(acl);
-
+
acl = pa_ip_acl_new("127.0.0.2");
assert(acl);
printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
@@ -67,17 +81,20 @@ int main(int argc, char *argv[]) {
assert(acl);
printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
pa_ip_acl_free(acl);
-
+
close(fd);
- fd = socket(PF_INET6, SOCK_STREAM, 0);
- assert(fd >= 0);
+#ifdef HAVE_IPV6
+ if ( (fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0 ) {
+ printf("Unable to open IPv6 socket, IPv6 tests ignored");
+ return 0;
+ }
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(22);
- inet_pton(AF_INET6, "::1", &sa6.sin6_addr);
-
+ pa_assert_se(inet_pton(AF_INET6, "::1", &sa6.sin6_addr) == 1);
+
r = connect(fd, (struct sockaddr*) &sa6, sizeof(sa6));
assert(r >= 0);
@@ -112,6 +129,7 @@ int main(int argc, char *argv[]) {
pa_ip_acl_free(acl);
close(fd);
-
+#endif
+
return 0;
}
diff --git a/src/tests/lock-autospawn-test.c b/src/tests/lock-autospawn-test.c
new file mode 100644
index 00000000..9ba61296
--- /dev/null
+++ b/src/tests/lock-autospawn-test.c
@@ -0,0 +1,109 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <pulsecore/poll.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/lock-autospawn.h>
+#include <pulse/util.h>
+
+static void thread_func(void*k) {
+ pa_assert_se(pa_autospawn_lock_init() >= 0);
+
+ pa_log("%i, Trying to acquire lock.", PA_PTR_TO_INT(k));
+
+ pa_assert_se(pa_autospawn_lock_acquire(TRUE) > 0);
+
+ pa_log("%i, Got the lock!, Sleeping for 5s", PA_PTR_TO_INT(k));
+
+ pa_msleep(5000);
+
+ pa_log("%i, Releasing", PA_PTR_TO_INT(k));
+
+ pa_autospawn_lock_release();
+
+ pa_autospawn_lock_done(FALSE);
+}
+
+static void thread_func2(void *k) {
+ int fd;
+
+ pa_assert_se((fd = pa_autospawn_lock_init()) >= 0);
+
+ pa_log("%i, Trying to acquire lock.", PA_PTR_TO_INT(k));
+
+ for (;;) {
+ struct pollfd pollfd;
+ int j;
+
+ if ((j = pa_autospawn_lock_acquire(FALSE)) > 0)
+ break;
+
+ pa_assert(j == 0);
+
+ memset(&pollfd, 0, sizeof(pollfd));
+ pollfd.fd = fd;
+ pollfd.events = POLLIN;
+
+ pa_assert_se(pa_poll(&pollfd, 1, -1) == 1);
+
+ pa_log("%i, woke up", PA_PTR_TO_INT(k));
+ }
+
+ pa_log("%i, Got the lock!, Sleeping for 5s", PA_PTR_TO_INT(k));
+
+ pa_msleep(5000);
+
+ pa_log("%i, Releasing", PA_PTR_TO_INT(k));
+
+ pa_autospawn_lock_release();
+
+ pa_autospawn_lock_done(FALSE);
+}
+
+int main(int argc, char**argv) {
+ pa_thread *a, *b, *c, *d;
+
+ pa_assert_se((a = pa_thread_new("test1", thread_func, PA_INT_TO_PTR(1))));
+ pa_assert_se((b = pa_thread_new("test2", thread_func2, PA_INT_TO_PTR(2))));
+ pa_assert_se((c = pa_thread_new("test3", thread_func2, PA_INT_TO_PTR(3))));
+ pa_assert_se((d = pa_thread_new("test4", thread_func, PA_INT_TO_PTR(4))));
+
+ pa_thread_join(a);
+ pa_thread_join(b);
+ pa_thread_join(c);
+ pa_thread_join(d);
+
+ pa_thread_free(a);
+ pa_thread_free(b);
+ pa_thread_free(c);
+ pa_thread_free(d);
+
+ pa_log("End");
+
+ return 0;
+}
diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c
index b06d0ed1..ab23de43 100644
--- a/src/tests/mainloop-test.c
+++ b/src/tests/mainloop-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -28,10 +26,11 @@
#include <sys/time.h>
#include <assert.h>
+#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulsecore/core-util.h>
-#include <pulsecore/gccmacro.h>
+#include <pulsecore/core-rtclock.h>
#ifdef GLIB_MAIN_LOOP
@@ -48,7 +47,7 @@ static pa_defer_event *de;
static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
unsigned char c;
- read(fd, &c, sizeof(c));
+ pa_assert_se(read(fd, &c, sizeof(c)) >= 0);
fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c);
a->defer_enable(de, 1);
}
@@ -68,7 +67,7 @@ static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, v
#endif
}
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
+int main(int argc, char *argv[]) {
pa_mainloop_api *a;
pa_io_event *ioe;
pa_time_event *te;
@@ -101,9 +100,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
de = a->defer_new(a, dcb, NULL);
assert(de);
- pa_gettimeofday(&tv);
- tv.tv_sec += 10;
- te = a->time_new(a, &tv, tcb, NULL);
+ te = a->time_new(a, pa_timeval_rtstore(&tv, pa_rtclock_now() + 2 * PA_USEC_PER_SEC, TRUE), tcb, NULL);
#if defined(GLIB_MAIN_LOOP)
g_main_loop_run(glib_main_loop);
@@ -121,6 +118,6 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
#else
pa_mainloop_free(m);
#endif
-
+
return 0;
}
diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c
index 7a68e6de..75a71dd1 100644
--- a/src/tests/mcalign-test.c
+++ b/src/tests/mcalign-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -33,45 +31,54 @@
#include <pulsecore/core-util.h>
#include <pulsecore/mcalign.h>
-#include <pulsecore/gccmacro.h>
/* A simple program for testing pa_mcalign */
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
- pa_mcalign *a = pa_mcalign_new(11, NULL);
+int main(int argc, char *argv[]) {
+ pa_mempool *p;
+ pa_mcalign *a;
pa_memchunk c;
+ p = pa_mempool_new(FALSE, 0);
+
+ a = pa_mcalign_new(11);
+
pa_memchunk_reset(&c);
- srand(time(NULL));
+ srand((unsigned) time(NULL));
for (;;) {
ssize_t r;
size_t l;
if (!c.memblock) {
- c.memblock = pa_memblock_new(2048, NULL);
+ c.memblock = pa_memblock_new(p, 2048);
c.index = c.length = 0;
}
- assert(c.index < c.memblock->length);
+ assert(c.index < pa_memblock_get_length(c.memblock));
+
+ l = pa_memblock_get_length(c.memblock) - c.index;
+
+ l = l <= 1 ? l : (size_t) rand() % (l-1) +1;
- l = c.memblock->length - c.index;
+ p = pa_memblock_acquire(c.memblock);
- l = l <= 1 ? l : rand() % (l-1) +1 ;
-
- if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) {
+ if ((r = read(STDIN_FILENO, (uint8_t*) p + c.index, l)) <= 0) {
+ pa_memblock_release(c.memblock);
fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF");
break;
}
- c.length = r;
+ pa_memblock_release(c.memblock);
+
+ c.length = (size_t) r;
pa_mcalign_push(a, &c);
fprintf(stderr, "Read %ld bytes\n", (long)r);
- c.index += r;
+ c.index += (size_t) r;
- if (c.index >= c.memblock->length) {
+ if (c.index >= pa_memblock_get_length(c.memblock)) {
pa_memblock_unref(c.memblock);
pa_memchunk_reset(&c);
}
@@ -82,7 +89,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
if (pa_mcalign_pop(a, &t) < 0)
break;
- pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL);
+ p = pa_memblock_acquire(t.memblock);
+ pa_loop_write(STDOUT_FILENO, (uint8_t*) p + t.index, t.length, NULL);
+ pa_memblock_release(t.memblock);
fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length);
pa_memblock_unref(t.memblock);
@@ -94,5 +103,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
if (c.memblock)
pa_memblock_unref(c.memblock);
+ pa_mempool_free(p);
+
return 0;
}
diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c
new file mode 100644
index 00000000..9cf6c78b
--- /dev/null
+++ b/src/tests/memblock-test.c
@@ -0,0 +1,174 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <pulsecore/memblock.h>
+#include <pulsecore/macro.h>
+#include <pulse/xmalloc.h>
+
+static void release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
+ printf("%s: Imported block %u is released.\n", (char*) userdata, block_id);
+}
+
+static void revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) {
+ printf("%s: Exported block %u is revoked.\n", (char*) userdata, block_id);
+}
+
+static void print_stats(pa_mempool *p, const char *text) {
+ const pa_mempool_stat*s = pa_mempool_get_stat(p);
+
+ printf("%s = {\n"
+ "n_allocated = %u\n"
+ "n_accumulated = %u\n"
+ "n_imported = %u\n"
+ "n_exported = %u\n"
+ "allocated_size = %u\n"
+ "accumulated_size = %u\n"
+ "imported_size = %u\n"
+ "exported_size = %u\n"
+ "n_too_large_for_pool = %u\n"
+ "n_pool_full = %u\n"
+ "}\n",
+ text,
+ (unsigned) pa_atomic_load(&s->n_allocated),
+ (unsigned) pa_atomic_load(&s->n_accumulated),
+ (unsigned) pa_atomic_load(&s->n_imported),
+ (unsigned) pa_atomic_load(&s->n_exported),
+ (unsigned) pa_atomic_load(&s->allocated_size),
+ (unsigned) pa_atomic_load(&s->accumulated_size),
+ (unsigned) pa_atomic_load(&s->imported_size),
+ (unsigned) pa_atomic_load(&s->exported_size),
+ (unsigned) pa_atomic_load(&s->n_too_large_for_pool),
+ (unsigned) pa_atomic_load(&s->n_pool_full));
+}
+
+int main(int argc, char *argv[]) {
+ pa_mempool *pool_a, *pool_b, *pool_c;
+ unsigned id_a, id_b, id_c;
+ pa_memexport *export_a, *export_b;
+ pa_memimport *import_b, *import_c;
+ pa_memblock *mb_a, *mb_b, *mb_c;
+ int r, i;
+ pa_memblock* blocks[5];
+ uint32_t id, shm_id;
+ size_t offset, size;
+ char *x;
+
+ const char txt[] = "This is a test!";
+
+ pool_a = pa_mempool_new(TRUE, 0);
+ pool_b = pa_mempool_new(TRUE, 0);
+ pool_c = pa_mempool_new(TRUE, 0);
+
+ pa_mempool_get_shm_id(pool_a, &id_a);
+ pa_mempool_get_shm_id(pool_b, &id_b);
+ pa_mempool_get_shm_id(pool_c, &id_c);
+
+ pa_assert(pool_a && pool_b && pool_c);
+
+ blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1);
+
+ blocks[1] = pa_memblock_new(pool_a, sizeof(txt));
+ x = pa_memblock_acquire(blocks[1]);
+ snprintf(x, pa_memblock_get_length(blocks[1]), "%s", txt);
+ pa_memblock_release(blocks[1]);
+
+ blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt));
+ x = pa_memblock_acquire(blocks[2]);
+ snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt);
+ pa_memblock_release(blocks[2]);
+
+ blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt));
+ blocks[4] = NULL;
+
+ for (i = 0; blocks[i]; i++) {
+ printf("Memory block %u\n", i);
+
+ mb_a = blocks[i];
+ pa_assert(mb_a);
+
+ export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A");
+ export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B");
+
+ pa_assert(export_a && export_b);
+
+ import_b = pa_memimport_new(pool_b, release_cb, (void*) "B");
+ import_c = pa_memimport_new(pool_c, release_cb, (void*) "C");
+
+ pa_assert(import_b && import_c);
+
+ r = pa_memexport_put(export_a, mb_a, &id, &shm_id, &offset, &size);
+ pa_assert(r >= 0);
+ pa_assert(shm_id == id_a);
+
+ printf("A: Memory block exported as %u\n", id);
+
+ mb_b = pa_memimport_get(import_b, id, shm_id, offset, size);
+ pa_assert(mb_b);
+ r = pa_memexport_put(export_b, mb_b, &id, &shm_id, &offset, &size);
+ pa_assert(r >= 0);
+ pa_assert(shm_id == id_a || shm_id == id_b);
+ pa_memblock_unref(mb_b);
+
+ printf("B: Memory block exported as %u\n", id);
+
+ mb_c = pa_memimport_get(import_c, id, shm_id, offset, size);
+ pa_assert(mb_c);
+ x = pa_memblock_acquire(mb_c);
+ printf("1 data=%s\n", x);
+ pa_memblock_release(mb_c);
+
+ print_stats(pool_a, "A");
+ print_stats(pool_b, "B");
+ print_stats(pool_c, "C");
+
+ pa_memexport_free(export_b);
+ x = pa_memblock_acquire(mb_c);
+ printf("2 data=%s\n", x);
+ pa_memblock_release(mb_c);
+ pa_memblock_unref(mb_c);
+
+ pa_memimport_free(import_b);
+
+ pa_memblock_unref(mb_a);
+
+ pa_memimport_free(import_c);
+ pa_memexport_free(export_a);
+ }
+
+ printf("vaccuuming...\n");
+
+ pa_mempool_vacuum(pool_a);
+ pa_mempool_vacuum(pool_b);
+ pa_mempool_vacuum(pool_c);
+
+ printf("vaccuuming done...\n");
+
+ pa_mempool_free(pool_a);
+ pa_mempool_free(pool_b);
+ pa_mempool_free(pool_c);
+
+ return 0;
+}
diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index af43d06f..b6c60039 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -26,122 +24,157 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
+#include <signal.h>
#include <pulsecore/memblockq.h>
#include <pulsecore/log.h>
+static void dump_chunk(const pa_memchunk *chunk) {
+ size_t n;
+ void *q;
+ char *e;
+
+ pa_assert(chunk);
+
+ q = pa_memblock_acquire(chunk->memblock);
+ for (e = (char*) q + chunk->index, n = 0; n < chunk->length; n++, e++)
+ printf("%c", *e);
+ pa_memblock_release(chunk->memblock);
+}
+
+static void dump(pa_memblockq *bq) {
+ pa_memchunk out;
+
+ pa_assert(bq);
+
+ /* First let's dump this as fixed block */
+ printf("FIXED >");
+ pa_memblockq_peek_fixed_size(bq, 64, &out);
+ dump_chunk(&out);
+ pa_memblock_unref(out.memblock);
+ printf("<\n");
+
+ /* Then let's dump the queue manually */
+ printf("MANUAL>");
+
+ for (;;) {
+ if (pa_memblockq_peek(bq, &out) < 0)
+ break;
+
+ dump_chunk(&out);
+ pa_memblock_unref(out.memblock);
+ pa_memblockq_drop(bq, out.length);
+ }
+
+ printf("<\n");
+}
+
int main(int argc, char *argv[]) {
int ret;
+
+ pa_mempool *p;
pa_memblockq *bq;
pa_memchunk chunk1, chunk2, chunk3, chunk4;
- pa_memblock *silence;
+ pa_memchunk silence;
- pa_log_set_maximal_level(PA_LOG_DEBUG);
-
- silence = pa_memblock_new_fixed((char*) "__", 2, 1, NULL);
- assert(silence);
+ pa_log_set_level(PA_LOG_DEBUG);
- bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence, NULL);
+ p = pa_mempool_new(FALSE, 0);
+
+ silence.memblock = pa_memblock_new_fixed(p, (char*) "__", 2, 1);
+ assert(silence.memblock);
+ silence.index = 0;
+ silence.length = pa_memblock_get_length(silence.memblock);
+
+ bq = pa_memblockq_new(0, 200, 10, 2, 4, 4, 40, &silence);
assert(bq);
- chunk1.memblock = pa_memblock_new_fixed((char*) "AA", 2, 1, NULL);
+ chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1);
chunk1.index = 0;
chunk1.length = 2;
assert(chunk1.memblock);
-
- chunk2.memblock = pa_memblock_new_fixed((char*) "TTBB", 4, 1, NULL);
+
+ chunk2.memblock = pa_memblock_new_fixed(p, (char*) "XX22", 4, 1);
chunk2.index = 2;
chunk2.length = 2;
assert(chunk2.memblock);
- chunk3.memblock = pa_memblock_new_fixed((char*) "ZZZZ", 4, 1, NULL);
+ chunk3.memblock = pa_memblock_new_fixed(p, (char*) "3333", 4, 1);
chunk3.index = 0;
chunk3.length = 4;
assert(chunk3.memblock);
- chunk4.memblock = pa_memblock_new_fixed((char*) "KKKKKKKK", 8, 1, NULL);
+ chunk4.memblock = pa_memblock_new_fixed(p, (char*) "44444444", 8, 1);
chunk4.index = 0;
chunk4.length = 8;
assert(chunk4.memblock);
ret = pa_memblockq_push(bq, &chunk1);
assert(ret == 0);
-
- ret = pa_memblockq_push(bq, &chunk1);
- assert(ret == 0);
-
- ret = pa_memblockq_push(bq, &chunk2);
- assert(ret == 0);
-
+
ret = pa_memblockq_push(bq, &chunk2);
assert(ret == 0);
- pa_memblockq_seek(bq, -6, 0);
ret = pa_memblockq_push(bq, &chunk3);
assert(ret == 0);
- pa_memblockq_seek(bq, -2, 0);
+ ret = pa_memblockq_push(bq, &chunk4);
+ assert(ret == 0);
+
+ pa_memblockq_seek(bq, -6, 0, TRUE);
ret = pa_memblockq_push(bq, &chunk3);
assert(ret == 0);
- pa_memblockq_seek(bq, -10, 0);
+ pa_memblockq_seek(bq, -2, 0, TRUE);
+ ret = pa_memblockq_push(bq, &chunk1);
+ assert(ret == 0);
+
+ pa_memblockq_seek(bq, -10, 0, TRUE);
ret = pa_memblockq_push(bq, &chunk4);
assert(ret == 0);
- pa_memblockq_seek(bq, 10, 0);
+ pa_memblockq_seek(bq, 10, 0, TRUE);
ret = pa_memblockq_push(bq, &chunk1);
assert(ret == 0);
- pa_memblockq_seek(bq, -6, 0);
+ pa_memblockq_seek(bq, -6, 0, TRUE);
ret = pa_memblockq_push(bq, &chunk2);
assert(ret == 0);
/* Test splitting */
- pa_memblockq_seek(bq, -12, 0);
+ pa_memblockq_seek(bq, -12, 0, TRUE);
ret = pa_memblockq_push(bq, &chunk1);
assert(ret == 0);
- pa_memblockq_seek(bq, 20, 0);
+ pa_memblockq_seek(bq, 20, 0, TRUE);
/* Test merging */
ret = pa_memblockq_push(bq, &chunk3);
assert(ret == 0);
- pa_memblockq_seek(bq, -2, 0);
+ pa_memblockq_seek(bq, -2, 0, TRUE);
chunk3.index += 2;
chunk3.length -= 2;
-
ret = pa_memblockq_push(bq, &chunk3);
assert(ret == 0);
-
- printf(">");
- pa_memblockq_shorten(bq, 6);
-
- for (;;) {
- pa_memchunk out;
- char *e;
- size_t n;
-
- if (pa_memblockq_peek(bq, &out) < 0)
- break;
+ pa_memblockq_seek(bq, 30, PA_SEEK_RELATIVE, TRUE);
- for (e = (char*) out.memblock->data + out.index, n = 0; n < out.length; n++)
- printf("%c", *e);
+ dump(bq);
+
+ pa_memblockq_rewind(bq, 52);
+
+ dump(bq);
- pa_memblock_unref(out.memblock);
- pa_memblockq_drop(bq, &out, out.length);
- }
-
- printf("<\n");
-
pa_memblockq_free(bq);
- pa_memblock_unref(silence);
+ pa_memblock_unref(silence.memblock);
pa_memblock_unref(chunk1.memblock);
pa_memblock_unref(chunk2.memblock);
pa_memblock_unref(chunk3.memblock);
pa_memblock_unref(chunk4.memblock);
-
+
+ pa_mempool_free(p);
+
return 0;
}
diff --git a/src/tests/mix-test.c b/src/tests/mix-test.c
new file mode 100644
index 00000000..7c05b8ed
--- /dev/null
+++ b/src/tests/mix-test.c
@@ -0,0 +1,264 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <pulse/sample.h>
+#include <pulse/volume.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/endianmacros.h>
+#include <pulsecore/memblock.h>
+#include <pulsecore/sample-util.h>
+
+static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
+ void *d;
+ unsigned i;
+
+ d = pa_memblock_acquire(chunk->memblock);
+
+ switch (ss->format) {
+
+ case PA_SAMPLE_U8:
+ case PA_SAMPLE_ULAW:
+ case PA_SAMPLE_ALAW: {
+ uint8_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf("0x%02x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_S16NE:
+ case PA_SAMPLE_S16RE: {
+ uint16_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf("0x%04x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_S24_32NE:
+ case PA_SAMPLE_S24_32RE:
+ case PA_SAMPLE_S32NE:
+ case PA_SAMPLE_S32RE: {
+ uint32_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf("0x%08x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_S24NE:
+ case PA_SAMPLE_S24RE: {
+ uint8_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
+ printf("0x%02x%02x%02xx ", *u, *(u+1), *(u+2));
+ u += 3;
+ }
+
+ break;
+ }
+
+ case PA_SAMPLE_FLOAT32NE:
+ case PA_SAMPLE_FLOAT32RE: {
+ float *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
+ printf("%1.5f ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u));
+ u++;
+ }
+
+ break;
+ }
+
+ default:
+ pa_assert_not_reached();
+ }
+
+ printf("\n");
+
+ pa_memblock_release(chunk->memblock);
+}
+
+static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
+ pa_memblock *r;
+ void *d;
+ unsigned i;
+
+ pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
+ d = pa_memblock_acquire(r);
+
+ switch (ss->format) {
+
+ case PA_SAMPLE_U8:
+ case PA_SAMPLE_ULAW:
+ case PA_SAMPLE_ALAW: {
+ static const uint8_t u8_samples[] = {
+ 0x00, 0xFF, 0x7F, 0x80, 0x9f,
+ 0x3f, 0x01, 0xF0, 0x20, 0x21
+ };
+
+ memcpy(d, u8_samples, sizeof(u8_samples));
+ break;
+ }
+
+ case PA_SAMPLE_S16NE:
+ case PA_SAMPLE_S16RE: {
+ static const uint16_t u16_samples[] = {
+ 0x0000, 0xFFFF, 0x7FFF, 0x8000, 0x9fff,
+ 0x3fff, 0x0001, 0xF000, 0x0020, 0x0021
+ };
+
+ memcpy(d, u16_samples, sizeof(u16_samples));
+ break;
+ }
+
+ case PA_SAMPLE_S24_32NE:
+ case PA_SAMPLE_S24_32RE:
+ case PA_SAMPLE_S32NE:
+ case PA_SAMPLE_S32RE: {
+ static const uint32_t u32_samples[] = {
+ 0x00000001, 0xFFFF0002, 0x7FFF0003, 0x80000004, 0x9fff0005,
+ 0x3fff0006, 0x00010007, 0xF0000008, 0x00200009, 0x0021000A
+ };
+
+ memcpy(d, u32_samples, sizeof(u32_samples));
+ break;
+ }
+
+ case PA_SAMPLE_S24NE:
+ case PA_SAMPLE_S24RE: {
+ /* Need to be on a byte array because they are not aligned */
+ static const uint8_t u24_samples[] = {
+ 0x00, 0x00, 0x01,
+ 0xFF, 0xFF, 0x02,
+ 0x7F, 0xFF, 0x03,
+ 0x80, 0x00, 0x04,
+ 0x9f, 0xff, 0x05,
+ 0x3f, 0xff, 0x06,
+ 0x01, 0x00, 0x07,
+ 0xF0, 0x00, 0x08,
+ 0x20, 0x00, 0x09,
+ 0x21, 0x00, 0x0A
+ };
+
+ memcpy(d, u24_samples, sizeof(u24_samples));
+ break;
+ }
+
+ case PA_SAMPLE_FLOAT32NE:
+ case PA_SAMPLE_FLOAT32RE: {
+ float *u = d;
+ static const float float_samples[] = {
+ 0.0f, -1.0f, 1.0f, 4711.0f, 0.222f,
+ 0.33f, -.3f, 99.0f, -0.555f, -.123f
+ };
+
+ if (ss->format == PA_SAMPLE_FLOAT32RE) {
+ for (i = 0; i < 10; i++)
+ u[i] = PA_FLOAT32_SWAP(float_samples[i]);
+ } else
+ memcpy(d, float_samples, sizeof(float_samples));
+
+ break;
+ }
+
+ default:
+ pa_assert_not_reached();
+ }
+
+ pa_memblock_release(r);
+
+ return r;
+}
+
+int main(int argc, char *argv[]) {
+ pa_mempool *pool;
+ pa_sample_spec a;
+ pa_cvolume v;
+
+ pa_log_set_level(PA_LOG_DEBUG);
+
+ pa_assert_se(pool = pa_mempool_new(FALSE, 0));
+
+ a.channels = 1;
+ a.rate = 44100;
+
+ v.channels = a.channels;
+ v.values[0] = pa_sw_volume_from_linear(0.9);
+
+ for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
+ pa_memchunk i, j, k;
+ pa_mix_info m[2];
+ void *ptr;
+
+ printf("=== mixing: %s\n", pa_sample_format_to_string(a.format));
+
+ /* Generate block */
+ i.memblock = generate_block(pool, &a);
+ i.length = pa_memblock_get_length(i.memblock);
+ i.index = 0;
+
+ dump_block(&a, &i);
+
+ /* Make a copy */
+ j = i;
+ pa_memblock_ref(j.memblock);
+ pa_memchunk_make_writable(&j, 0);
+
+ /* Adjust volume of the copy */
+ pa_volume_memchunk(&j, &a, &v);
+
+ dump_block(&a, &j);
+
+ m[0].chunk = i;
+ m[0].volume.values[0] = PA_VOLUME_NORM;
+ m[0].volume.channels = a.channels;
+ m[1].chunk = j;
+ m[1].volume.values[0] = PA_VOLUME_NORM;
+ m[1].volume.channels = a.channels;
+
+ k.memblock = pa_memblock_new(pool, i.length);
+ k.length = i.length;
+ k.index = 0;
+
+ ptr = (uint8_t*) pa_memblock_acquire(k.memblock) + k.index;
+ pa_mix(m, 2, ptr, k.length, &a, NULL, FALSE);
+ pa_memblock_release(k.memblock);
+
+ dump_block(&a, &k);
+
+ pa_memblock_unref(i.memblock);
+ pa_memblock_unref(j.memblock);
+ pa_memblock_unref(k.memblock);
+ }
+
+ pa_mempool_free(pool);
+
+ return 0;
+}
diff --git a/src/tests/once-test.c b/src/tests/once-test.c
new file mode 100644
index 00000000..8a9995da
--- /dev/null
+++ b/src/tests/once-test.c
@@ -0,0 +1,111 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include <pulsecore/thread.h>
+#include <pulsecore/once.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/atomic.h>
+#include <pulse/xmalloc.h>
+
+static pa_once once = PA_ONCE_INIT;
+static volatile unsigned n_run = 0;
+static const char * volatile ran_by = NULL;
+#ifdef HAVE_PTHREAD
+static pthread_barrier_t barrier;
+#endif
+static unsigned n_cpu;
+
+#define N_ITERATIONS 500
+#define N_THREADS 100
+
+static void once_func(void) {
+ n_run++;
+ ran_by = (const char*) pa_thread_get_data(pa_thread_self());
+}
+
+static void thread_func(void *data) {
+#ifdef HAVE_PTHREAD
+ int r;
+
+#ifdef HAVE_PTHREAD_SETAFFINITY_NP
+ static pa_atomic_t i_cpu = PA_ATOMIC_INIT(0);
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ CPU_SET((size_t) (pa_atomic_inc(&i_cpu) % n_cpu), &mask);
+ pa_assert_se(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == 0);
+#endif
+
+ /* pa_log("started up: %s", data); */
+
+ r = pthread_barrier_wait(&barrier);
+ pa_assert(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD);
+#endif /* HAVE_PTHREAD */
+
+ pa_run_once(&once, once_func);
+}
+
+int main(int argc, char *argv[]) {
+ unsigned n, i;
+
+ n_cpu = pa_ncpus();
+
+ for (n = 0; n < N_ITERATIONS; n++) {
+ pa_thread* threads[N_THREADS];
+
+#ifdef HAVE_PTHREAD
+ pa_assert_se(pthread_barrier_init(&barrier, NULL, N_THREADS) == 0);
+#endif
+
+ /* Yes, kinda ugly */
+ pa_zero(once);
+
+ for (i = 0; i < N_THREADS; i++)
+ threads[i] = pa_thread_new("once", thread_func, pa_sprintf_malloc("Thread #%i", i+1));
+
+ for (i = 0; i < N_THREADS; i++)
+ pa_thread_join(threads[i]);
+
+ pa_assert(n_run == 1);
+ pa_log("ran by %s", ran_by);
+
+ for (i = 0; i < N_THREADS; i++) {
+ pa_xfree(pa_thread_get_data(threads[i]));
+ pa_thread_free(threads[i]);
+ }
+
+ n_run = 0;
+ ran_by = NULL;
+
+#ifdef HAVE_PTHREAD
+ pa_assert_se(pthread_barrier_destroy(&barrier) == 0);
+#endif
+ }
+
+ return 0;
+}
diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c
index 364e1ad6..7d119c44 100644
--- a/src/tests/pacat-simple.c
+++ b/src/tests/pacat-simple.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -31,11 +29,10 @@
#include <pulse/simple.h>
#include <pulse/error.h>
-#include <pulsecore/gccmacro.h>
#define BUFSIZE 1024
-int main(PA_GCC_UNUSED int argc, char*argv[]) {
+int main(int argc, char*argv[]) {
/* The Sample format to use */
static const pa_sample_spec ss = {
@@ -43,7 +40,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
.rate = 44100,
.channels = 2
};
-
+
pa_simple *s = NULL;
int ret = 1;
int error;
@@ -61,10 +58,10 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
fprintf(stderr, __FILE__": dup2() failed: %s\n", strerror(errno));
goto finish;
}
-
+
close(fd);
}
-
+
/* Create a new playback stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
@@ -90,13 +87,13 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) {
if (r == 0) /* EOF */
break;
-
+
fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno));
goto finish;
}
/* ... and play it */
- if (pa_simple_write(s, buf, r, &error) < 0) {
+ if (pa_simple_write(s, buf, (size_t) r, &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error));
goto finish;
}
@@ -114,6 +111,6 @@ finish:
if (s)
pa_simple_free(s);
-
+
return ret;
}
diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c
index 45a52288..dfa43f0f 100644
--- a/src/tests/parec-simple.c
+++ b/src/tests/parec-simple.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -30,7 +28,6 @@
#include <pulse/simple.h>
#include <pulse/error.h>
-#include <pulsecore/gccmacro.h>
#define BUFSIZE 1024
@@ -46,16 +43,16 @@ static ssize_t loop_write(int fd, const void*data, size_t size) {
if (r == 0)
break;
-
+
ret += r;
data = (const uint8_t*) data + r;
- size -= r;
+ size -= (size_t) r;
}
return ret;
}
-int main(PA_GCC_UNUSED int argc, char*argv[]) {
+int main(int argc, char*argv[]) {
/* The sample type to use */
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
@@ -74,7 +71,6 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
for (;;) {
uint8_t buf[BUFSIZE];
- ssize_t r;
/* Record some data ... */
if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
@@ -83,7 +79,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
}
/* And write it to STDOUT */
- if ((r = loop_write(STDOUT_FILENO, buf, sizeof(buf))) <= 0) {
+ if (loop_write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) {
fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
goto finish;
}
@@ -95,6 +91,6 @@ finish:
if (s)
pa_simple_free(s);
-
+
return ret;
}
diff --git a/src/tests/prioq-test.c b/src/tests/prioq-test.c
new file mode 100644
index 00000000..120b512b
--- /dev/null
+++ b/src/tests/prioq-test.c
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/prioq.h>
+#include <pulsecore/macro.h>
+
+#define N 1024
+
+int main(int argc, char *argv[]) {
+ pa_prioq *q;
+ unsigned i;
+
+ srand(0);
+
+ q = pa_prioq_new(pa_idxset_trivial_compare_func);
+
+ /* Fill in 1024 */
+ for (i = 0; i < N; i++)
+ pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand()));
+
+ /* Remove half of it again */
+ for (i = 0; i < N/2; i++){
+ unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q));
+ pa_log("%16u", u);
+ }
+
+ pa_log("Refilling");
+
+ /* Fill in another 1024 */
+ for (i = 0; i < N; i++)
+ pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand()));
+
+
+ /* Remove everything */
+ while (!pa_prioq_isempty(q)) {
+ unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q));
+ pa_log("%16u", u);
+ }
+
+ pa_prioq_free(q, NULL, NULL);
+
+ return 0;
+}
diff --git a/src/tests/proplist-test.c b/src/tests/proplist-test.c
new file mode 100644
index 00000000..27a0d3fe
--- /dev/null
+++ b/src/tests/proplist-test.c
@@ -0,0 +1,96 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <pulse/proplist.h>
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+
+int main(int argc, char*argv[]) {
+ pa_modargs *ma;
+ pa_proplist *a, *b, *c, *d;
+ char *s, *t, *u, *v;
+ const char *text;
+ const char *x[] = { "foo", NULL };
+
+ a = pa_proplist_new();
+ pa_assert_se(pa_proplist_sets(a, PA_PROP_MEDIA_TITLE, "Brandenburgische Konzerte") == 0);
+ pa_assert_se(pa_proplist_sets(a, PA_PROP_MEDIA_ARTIST, "Johann Sebastian Bach") == 0);
+
+ b = pa_proplist_new();
+ pa_assert_se(pa_proplist_sets(b, PA_PROP_MEDIA_TITLE, "Goldbergvariationen") == 0);
+ pa_assert_se(pa_proplist_set(b, PA_PROP_MEDIA_ICON, "\0\1\2\3\4\5\6\7", 8) == 0);
+
+ pa_proplist_update(a, PA_UPDATE_MERGE, b);
+
+ pa_assert_se(!pa_proplist_gets(a, PA_PROP_MEDIA_ICON));
+
+ printf("%s\n", pa_strnull(pa_proplist_gets(a, PA_PROP_MEDIA_TITLE)));
+ pa_assert_se(pa_proplist_unset(b, PA_PROP_MEDIA_TITLE) == 0);
+
+ s = pa_proplist_to_string(a);
+ t = pa_proplist_to_string(b);
+ printf("---\n%s---\n%s", s, t);
+
+ c = pa_proplist_from_string(s);
+ u = pa_proplist_to_string(c);
+ pa_assert_se(pa_streq(s, u));
+
+ pa_xfree(s);
+ pa_xfree(t);
+ pa_xfree(u);
+
+ pa_proplist_free(a);
+ pa_proplist_free(b);
+ pa_proplist_free(c);
+
+ text = " eins = zwei drei = \"\\\"vier\\\"\" fuenf=sechs sieben ='\\a\\c\\h\\t\\'\\\"' neun= hex:0123456789abCDef ";
+
+ printf("%s\n", text);
+ d = pa_proplist_from_string(text);
+ v = pa_proplist_to_string(d);
+ pa_proplist_free(d);
+ printf("%s\n", v);
+ d = pa_proplist_from_string(v);
+ pa_xfree(v);
+ v = pa_proplist_to_string(d);
+ pa_proplist_free(d);
+ printf("%s\n", v);
+ pa_xfree(v);
+
+ pa_assert_se(ma = pa_modargs_new("foo='foobar=waldo foo2=\"lj\\\\\"dhflh\" foo3=\\'kjlskj\\\\\\'\\''", x));
+ pa_assert_se(a = pa_proplist_new());
+
+ pa_assert_se(pa_modargs_get_proplist(ma, "foo", a, PA_UPDATE_REPLACE) >= 0);
+
+ printf("%s\n", v = pa_proplist_to_string(a));
+ pa_xfree(v);
+
+ pa_proplist_free(a);
+ pa_modargs_free(ma);
+
+ return 0;
+}
diff --git a/src/tests/queue-test.c b/src/tests/queue-test.c
new file mode 100644
index 00000000..b21775e8
--- /dev/null
+++ b/src/tests/queue-test.c
@@ -0,0 +1,64 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pulsecore/queue.h>
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+
+int main(int argc, char *argv[]) {
+ pa_queue *q;
+
+ pa_assert_se(q = pa_queue_new());
+
+ pa_assert(pa_queue_isempty(q));
+
+ pa_queue_push(q, (void*) "eins");
+ pa_log("%s\n", (char*) pa_queue_pop(q));
+
+ pa_assert(pa_queue_isempty(q));
+
+ pa_queue_push(q, (void*) "zwei");
+ pa_queue_push(q, (void*) "drei");
+ pa_queue_push(q, (void*) "vier");
+
+ pa_log("%s\n", (char*) pa_queue_pop(q));
+ pa_log("%s\n", (char*) pa_queue_pop(q));
+
+ pa_queue_push(q, (void*) "fuenf");
+
+ pa_log("%s\n", (char*) pa_queue_pop(q));
+ pa_log("%s\n", (char*) pa_queue_pop(q));
+
+ pa_assert(pa_queue_isempty(q));
+
+ pa_queue_push(q, (void*) "sechs");
+ pa_queue_push(q, (void*) "sieben");
+
+ pa_queue_free(q, NULL, NULL);
+
+ return 0;
+}
diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c
new file mode 100644
index 00000000..19f5582b
--- /dev/null
+++ b/src/tests/remix-test.c
@@ -0,0 +1,83 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <pulse/sample.h>
+
+#include <pulsecore/resampler.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/memblock.h>
+
+int main(int argc, char *argv[]) {
+
+ static const pa_channel_map maps[] = {
+ { 1, { PA_CHANNEL_POSITION_MONO } },
+ { 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } },
+ { 3, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER } },
+ { 3, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_LFE } },
+ { 3, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_CENTER } },
+ { 4, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE } },
+ { 4, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_REAR_CENTER } },
+ { 4, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT } },
+ { 5, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_CENTER } },
+ { 5, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE } },
+ { 6, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_CENTER } },
+ { 8, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT } },
+ { 0, { 0 } }
+ };
+
+ unsigned i, j;
+ pa_mempool *pool;
+
+ pa_log_set_level(PA_LOG_DEBUG);
+
+ pa_assert_se(pool = pa_mempool_new(FALSE, 0));
+
+ for (i = 0; maps[i].channels > 0; i++)
+ for (j = 0; maps[j].channels > 0; j++) {
+ char a[PA_CHANNEL_MAP_SNPRINT_MAX], b[PA_CHANNEL_MAP_SNPRINT_MAX];
+ pa_resampler *r;
+ pa_sample_spec ss1, ss2;
+
+ pa_log_info("Converting from '%s' to '%s'.\n", pa_channel_map_snprint(a, sizeof(a), &maps[i]), pa_channel_map_snprint(b, sizeof(b), &maps[j]));
+
+ ss1.channels = maps[i].channels;
+ ss2.channels = maps[j].channels;
+
+ ss1.rate = ss2.rate = 44100;
+ ss1.format = ss2.format = PA_SAMPLE_S16NE;
+
+ r = pa_resampler_new(pool, &ss1, &maps[i], &ss2, &maps[j], PA_RESAMPLER_AUTO, 0);
+
+ /* We don't really care for the resampler. We just want to
+ * see the remixing debug output. */
+
+ pa_resampler_free(r);
+ }
+
+
+ pa_mempool_free(pool);
+
+ return 0;
+}
diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c
new file mode 100644
index 00000000..78461da5
--- /dev/null
+++ b/src/tests/resampler-test.c
@@ -0,0 +1,487 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <getopt.h>
+#include <locale.h>
+
+#include <pulse/i18n.h>
+#include <pulse/pulseaudio.h>
+
+#include <pulse/rtclock.h>
+#include <pulse/sample.h>
+#include <pulse/volume.h>
+
+#include <pulsecore/resampler.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/endianmacros.h>
+#include <pulsecore/memblock.h>
+#include <pulsecore/sample-util.h>
+#include <pulsecore/core-util.h>
+
+static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
+ void *d;
+ unsigned i;
+
+ d = pa_memblock_acquire(chunk->memblock);
+
+ switch (ss->format) {
+
+ case PA_SAMPLE_U8:
+ case PA_SAMPLE_ULAW:
+ case PA_SAMPLE_ALAW: {
+ uint8_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf(" 0x%02x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_S16NE:
+ case PA_SAMPLE_S16RE: {
+ uint16_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf(" 0x%04x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_S32NE:
+ case PA_SAMPLE_S32RE: {
+ uint32_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf("0x%08x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_S24_32NE:
+ case PA_SAMPLE_S24_32RE: {
+ uint32_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+ printf("0x%08x ", *(u++));
+
+ break;
+ }
+
+ case PA_SAMPLE_FLOAT32NE:
+ case PA_SAMPLE_FLOAT32RE: {
+ float *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
+ printf("%4.3g ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u));
+ u++;
+ }
+
+ break;
+ }
+
+ case PA_SAMPLE_S24LE:
+ case PA_SAMPLE_S24BE: {
+ uint8_t *u = d;
+
+ for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
+ printf(" 0x%06x ", PA_READ24NE(u));
+ u += pa_frame_size(ss);
+ }
+
+ break;
+ }
+
+ default:
+ pa_assert_not_reached();
+ }
+
+ printf("\n");
+
+ pa_memblock_release(chunk->memblock);
+}
+
+static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
+ pa_memblock *r;
+ void *d;
+ unsigned i;
+
+ pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
+ d = pa_memblock_acquire(r);
+
+ switch (ss->format) {
+
+ case PA_SAMPLE_U8:
+ case PA_SAMPLE_ULAW:
+ case PA_SAMPLE_ALAW: {
+ uint8_t *u = d;
+
+ u[0] = 0x00;
+ u[1] = 0xFF;
+ u[2] = 0x7F;
+ u[3] = 0x80;
+ u[4] = 0x9f;
+ u[5] = 0x3f;
+ u[6] = 0x1;
+ u[7] = 0xF0;
+ u[8] = 0x20;
+ u[9] = 0x21;
+ break;
+ }
+
+ case PA_SAMPLE_S16NE:
+ case PA_SAMPLE_S16RE: {
+ uint16_t *u = d;
+
+ u[0] = 0x0000;
+ u[1] = 0xFFFF;
+ u[2] = 0x7FFF;
+ u[3] = 0x8000;
+ u[4] = 0x9fff;
+ u[5] = 0x3fff;
+ u[6] = 0x1;
+ u[7] = 0xF000;
+ u[8] = 0x20;
+ u[9] = 0x21;
+ break;
+ }
+
+ case PA_SAMPLE_S32NE:
+ case PA_SAMPLE_S32RE: {
+ uint32_t *u = d;
+
+ u[0] = 0x00000001;
+ u[1] = 0xFFFF0002;
+ u[2] = 0x7FFF0003;
+ u[3] = 0x80000004;
+ u[4] = 0x9fff0005;
+ u[5] = 0x3fff0006;
+ u[6] = 0x10007;
+ u[7] = 0xF0000008;
+ u[8] = 0x200009;
+ u[9] = 0x21000A;
+ break;
+ }
+
+ case PA_SAMPLE_S24_32NE:
+ case PA_SAMPLE_S24_32RE: {
+ uint32_t *u = d;
+
+ u[0] = 0x000001;
+ u[1] = 0xFF0002;
+ u[2] = 0x7F0003;
+ u[3] = 0x800004;
+ u[4] = 0x9f0005;
+ u[5] = 0x3f0006;
+ u[6] = 0x107;
+ u[7] = 0xF00008;
+ u[8] = 0x2009;
+ u[9] = 0x210A;
+ break;
+ }
+
+ case PA_SAMPLE_FLOAT32NE:
+ case PA_SAMPLE_FLOAT32RE: {
+ float *u = d;
+
+ u[0] = 0.0f;
+ u[1] = -1.0f;
+ u[2] = 1.0f;
+ u[3] = 4711.0f;
+ u[4] = 0.222f;
+ u[5] = 0.33f;
+ u[6] = -.3f;
+ u[7] = 99.0f;
+ u[8] = -0.555f;
+ u[9] = -.123f;
+
+ if (ss->format == PA_SAMPLE_FLOAT32RE)
+ for (i = 0; i < 10; i++)
+ u[i] = PA_FLOAT32_SWAP(u[i]);
+
+ break;
+ }
+
+ case PA_SAMPLE_S24NE:
+ case PA_SAMPLE_S24RE: {
+ uint8_t *u = d;
+
+ PA_WRITE24NE(u, 0x000001);
+ PA_WRITE24NE(u+3, 0xFF0002);
+ PA_WRITE24NE(u+6, 0x7F0003);
+ PA_WRITE24NE(u+9, 0x800004);
+ PA_WRITE24NE(u+12, 0x9f0005);
+ PA_WRITE24NE(u+15, 0x3f0006);
+ PA_WRITE24NE(u+18, 0x107);
+ PA_WRITE24NE(u+21, 0xF00008);
+ PA_WRITE24NE(u+24, 0x2009);
+ PA_WRITE24NE(u+27, 0x210A);
+ break;
+ }
+
+ default:
+ pa_assert_not_reached();
+ }
+
+ pa_memblock_release(r);
+
+ return r;
+}
+
+static void help(const char *argv0) {
+ printf(_("%s [options]\n\n"
+ "-h, --help Show this help\n"
+ "-v, --verbose Print debug messages\n"
+ " --from-rate=SAMPLERATE From sample rate in Hz (defaults to 44100)\n"
+ " --from-format=SAMPLEFORMAT From sample type (defaults to s16le)\n"
+ " --from-channels=CHANNELS From number of channels (defaults to 1)\n"
+ " --to-rate=SAMPLERATE To sample rate in Hz (defaults to 44100)\n"
+ " --to-format=SAMPLEFORMAT To sample type (defaults to s16le)\n"
+ " --to-channels=CHANNELS To number of channels (defaults to 1)\n"
+ " --resample-method=METHOD Resample method (defaults to auto)\n"
+ " --seconds=SECONDS From stream duration (defaults to 60)\n"
+ "\n"
+ "If the formats are not specified, the test performs all formats combinations,\n"
+ "back and forth.\n"
+ "\n"
+ "Sample type must be one of s16le, s16be, u8, float32le, float32be, ulaw, alaw,\n"
+ "32le, s32be (defaults to s16ne)\n"
+ "\n"
+ "See --dump-resample-methods for possible values of resample methods.\n"),
+ argv0);
+}
+
+enum {
+ ARG_VERSION = 256,
+ ARG_FROM_SAMPLERATE,
+ ARG_FROM_SAMPLEFORMAT,
+ ARG_FROM_CHANNELS,
+ ARG_TO_SAMPLERATE,
+ ARG_TO_SAMPLEFORMAT,
+ ARG_TO_CHANNELS,
+ ARG_SECONDS,
+ ARG_RESAMPLE_METHOD,
+ ARG_DUMP_RESAMPLE_METHODS
+};
+
+static void dump_resample_methods(void) {
+ int i;
+
+ for (i = 0; i < PA_RESAMPLER_MAX; i++)
+ if (pa_resample_method_supported(i))
+ printf("%s\n", pa_resample_method_to_string(i));
+
+}
+
+int main(int argc, char *argv[]) {
+ pa_mempool *pool = NULL;
+ pa_sample_spec a, b;
+ pa_cvolume v;
+ int ret = 1, verbose = 0, c;
+ pa_bool_t all_formats = TRUE;
+ pa_resample_method_t method;
+ int seconds;
+
+ static const struct option long_options[] = {
+ {"help", 0, NULL, 'h'},
+ {"verbose", 0, NULL, 'v'},
+ {"version", 0, NULL, ARG_VERSION},
+ {"from-rate", 1, NULL, ARG_FROM_SAMPLERATE},
+ {"from-format", 1, NULL, ARG_FROM_SAMPLEFORMAT},
+ {"from-channels", 1, NULL, ARG_FROM_CHANNELS},
+ {"to-rate", 1, NULL, ARG_TO_SAMPLERATE},
+ {"to-format", 1, NULL, ARG_TO_SAMPLEFORMAT},
+ {"to-channels", 1, NULL, ARG_TO_CHANNELS},
+ {"seconds", 1, NULL, ARG_SECONDS},
+ {"resample-method", 1, NULL, ARG_RESAMPLE_METHOD},
+ {"dump-resample-methods", 0, NULL, ARG_DUMP_RESAMPLE_METHODS},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
+
+ pa_log_set_level(PA_LOG_DEBUG);
+
+ pa_assert_se(pool = pa_mempool_new(FALSE, 0));
+
+ a.channels = b.channels = 1;
+ a.rate = b.rate = 44100;
+ a.format = b.format = PA_SAMPLE_S16LE;
+ v.channels = a.channels;
+ v.values[0] = pa_sw_volume_from_linear(0.5);
+
+ method = PA_RESAMPLER_AUTO;
+ seconds = 60;
+
+ while ((c = getopt_long(argc, argv, "hv", long_options, NULL)) != -1) {
+
+ switch (c) {
+ case 'h' :
+ help(argv[0]);
+ ret = 0;
+ goto quit;
+
+ case 'v':
+ pa_log_set_level(PA_LOG_DEBUG);
+ verbose = 1;
+ break;
+
+ case ARG_VERSION:
+ printf(_("%s %s\n"), argv[0], PACKAGE_VERSION);
+ ret = 0;
+ goto quit;
+
+ case ARG_DUMP_RESAMPLE_METHODS:
+ dump_resample_methods();
+ ret = 0;
+ goto quit;
+
+ case ARG_FROM_CHANNELS:
+ a.channels = (uint8_t) atoi(optarg);
+ break;
+
+ case ARG_FROM_SAMPLEFORMAT:
+ a.format = pa_parse_sample_format(optarg);
+ all_formats = FALSE;
+ break;
+
+ case ARG_FROM_SAMPLERATE:
+ a.rate = (uint32_t) atoi(optarg);
+ break;
+
+ case ARG_TO_CHANNELS:
+ b.channels = (uint8_t) atoi(optarg);
+ break;
+
+ case ARG_TO_SAMPLEFORMAT:
+ b.format = pa_parse_sample_format(optarg);
+ all_formats = FALSE;
+ break;
+
+ case ARG_TO_SAMPLERATE:
+ b.rate = (uint32_t) atoi(optarg);
+ break;
+
+ case ARG_SECONDS:
+ seconds = atoi(optarg);
+ break;
+
+ case ARG_RESAMPLE_METHOD:
+ if (*optarg == '\0' || pa_streq(optarg, "help")) {
+ dump_resample_methods();
+ ret = 0;
+ goto quit;
+ }
+ method = pa_parse_resample_method(optarg);
+ break;
+
+ default:
+ goto quit;
+ }
+ }
+
+ ret = 0;
+ pa_assert_se(pool = pa_mempool_new(FALSE, 0));
+
+ if (!all_formats) {
+
+ pa_resampler *resampler;
+ pa_memchunk i, j;
+ pa_usec_t ts;
+
+ if (verbose) {
+ printf(_("Compilation CFLAGS: %s\n"), PA_CFLAGS);
+ printf(_("=== %d seconds: %d Hz %d ch (%s) -> %d Hz %d ch (%s)\n"), seconds,
+ a.rate, a.channels, pa_sample_format_to_string(a.format),
+ b.rate, b.channels, pa_sample_format_to_string(b.format));
+ }
+
+ ts = pa_rtclock_now();
+ pa_assert_se(resampler = pa_resampler_new(pool, &a, NULL, &b, NULL, method, 0));
+ printf("init: %llu\n", (long long unsigned)(pa_rtclock_now() - ts));
+
+ i.memblock = pa_memblock_new(pool, pa_usec_to_bytes(1*PA_USEC_PER_SEC, &a) / pa_frame_size(&a));
+
+ ts = pa_rtclock_now();
+ i.length = pa_memblock_get_length(i.memblock);
+ i.index = 0;
+ while (seconds--) {
+ pa_resampler_run(resampler, &i, &j);
+ pa_memblock_unref(j.memblock);
+ }
+ printf("resampling: %llu\n", (long long unsigned)(pa_rtclock_now() - ts));
+ pa_memblock_unref(i.memblock);
+
+ pa_resampler_free(resampler);
+
+ goto quit;
+ }
+
+ for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
+ for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) {
+ pa_resampler *forth, *back;
+ pa_memchunk i, j, k;
+
+ if (verbose)
+ printf("=== %s -> %s -> %s -> /2\n",
+ pa_sample_format_to_string(a.format),
+ pa_sample_format_to_string(b.format),
+ pa_sample_format_to_string(a.format));
+
+ pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, method, 0));
+ pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, method, 0));
+
+ i.memblock = generate_block(pool, &a);
+ i.length = pa_memblock_get_length(i.memblock);
+ i.index = 0;
+ pa_resampler_run(forth, &i, &j);
+ pa_resampler_run(back, &j, &k);
+
+ printf("before: ");
+ dump_block(&a, &i);
+ printf("after : ");
+ dump_block(&b, &j);
+ printf("reverse: ");
+ dump_block(&a, &k);
+
+ pa_memblock_unref(j.memblock);
+ pa_memblock_unref(k.memblock);
+
+ pa_volume_memchunk(&i, &a, &v);
+ printf("volume: ");
+ dump_block(&a, &i);
+
+ pa_memblock_unref(i.memblock);
+
+ pa_resampler_free(forth);
+ pa_resampler_free(back);
+ }
+ }
+
+ quit:
+ if (pool)
+ pa_mempool_free(pool);
+
+ return ret;
+}
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
new file mode 100644
index 00000000..6a6b73a8
--- /dev/null
+++ b/src/tests/rtpoll-test.c
@@ -0,0 +1,85 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+
+#include <pulsecore/poll.h>
+#include <pulsecore/log.h>
+#include <pulsecore/rtpoll.h>
+
+static int before(pa_rtpoll_item *i) {
+ pa_log("before");
+ return 0;
+}
+
+static void after(pa_rtpoll_item *i) {
+ pa_log("after");
+}
+
+static int worker(pa_rtpoll_item *w) {
+ pa_log("worker");
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ pa_rtpoll *p;
+ pa_rtpoll_item *i, *w;
+ struct pollfd *pollfd;
+
+ p = pa_rtpoll_new();
+
+ i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1);
+ pa_rtpoll_item_set_before_callback(i, before);
+ pa_rtpoll_item_set_after_callback(i, after);
+
+ pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
+ pollfd->fd = 0;
+ pollfd->events = POLLIN;
+
+ w = pa_rtpoll_item_new(p, PA_RTPOLL_NORMAL, 0);
+ pa_rtpoll_item_set_before_callback(w, worker);
+
+ pa_rtpoll_set_timer_relative(p, 10000000); /* 10 s */
+
+ pa_rtpoll_run(p, 1);
+
+ pa_rtpoll_item_free(i);
+
+ i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1);
+ pa_rtpoll_item_set_before_callback(i, before);
+ pa_rtpoll_item_set_after_callback(i, after);
+
+ pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
+ pollfd->fd = 0;
+ pollfd->events = POLLIN;
+
+ pa_rtpoll_run(p, 1);
+
+ pa_rtpoll_item_free(i);
+
+ pa_rtpoll_item_free(w);
+
+ pa_rtpoll_free(p);
+
+ return 0;
+}
diff --git a/src/tests/rtstutter.c b/src/tests/rtstutter.c
new file mode 100644
index 00000000..739683d5
--- /dev/null
+++ b/src/tests/rtstutter.c
@@ -0,0 +1,117 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <inttypes.h>
+
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include <pulse/util.h>
+#include <pulse/timeval.h>
+#include <pulse/gccmacro.h>
+
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-rtclock.h>
+
+static int msec_lower, msec_upper;
+
+static void work(void *p) PA_GCC_NORETURN;
+
+static void work(void *p) {
+
+ pa_log_notice("CPU%i: Created thread.", PA_PTR_TO_UINT(p));
+
+ pa_make_realtime(12);
+
+#ifdef HAVE_PTHREAD_SETAFFINITY_NP
+{
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ CPU_SET((size_t) PA_PTR_TO_UINT(p), &mask);
+ pa_assert_se(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == 0);
+}
+#endif
+
+ for (;;) {
+ struct timeval now, end;
+ uint64_t usec;
+
+ pa_log_notice("CPU%i: Sleeping for 1s", PA_PTR_TO_UINT(p));
+ pa_msleep(1000);
+
+ usec =
+ (uint64_t) ((((double) rand())*(double)(msec_upper-msec_lower)*PA_USEC_PER_MSEC)/RAND_MAX) +
+ (uint64_t) ((uint64_t) msec_lower*PA_USEC_PER_MSEC);
+
+ pa_log_notice("CPU%i: Freezing for %ims", PA_PTR_TO_UINT(p), (int) (usec/PA_USEC_PER_MSEC));
+
+ pa_rtclock_get(&end);
+ pa_timeval_add(&end, usec);
+
+ do {
+ pa_rtclock_get(&now);
+ } while (pa_timeval_cmp(&now, &end) < 0);
+ }
+}
+
+int main(int argc, char*argv[]) {
+ unsigned n;
+
+ pa_log_set_level(PA_LOG_INFO);
+
+ srand((unsigned) time(NULL));
+
+ if (argc >= 3) {
+ msec_lower = atoi(argv[1]);
+ msec_upper = atoi(argv[2]);
+ } else if (argc >= 2) {
+ msec_lower = 0;
+ msec_upper = atoi(argv[1]);
+ } else {
+ msec_lower = 0;
+ msec_upper = 1000;
+ }
+
+ pa_assert(msec_upper > 0);
+ pa_assert(msec_upper >= msec_lower);
+
+ pa_log_notice("Creating random latencies in the range of %ims to %ims.", msec_lower, msec_upper);
+
+ for (n = 1; n < pa_ncpus(); n++) {
+ pa_assert_se(pa_thread_new("rtstutter", work, PA_UINT_TO_PTR(n)));
+ }
+
+ work(PA_INT_TO_PTR(0));
+
+ return 0;
+}
diff --git a/src/tests/sig2str-test.c b/src/tests/sig2str-test.c
new file mode 100644
index 00000000..0cd929ca
--- /dev/null
+++ b/src/tests/sig2str-test.c
@@ -0,0 +1,37 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdio.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+
+int main(int argc, char *argv[]) {
+ int sig;
+
+ for (sig = -1; sig <= NSIG; sig++)
+ printf("%i = %s\n", sig, pa_sig2str(sig));
+
+ return 0;
+}
diff --git a/src/tests/sigbus-test.c b/src/tests/sigbus-test.c
new file mode 100644
index 00000000..4b9ca840
--- /dev/null
+++ b/src/tests/sigbus-test.c
@@ -0,0 +1,70 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2009 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <pulsecore/memtrap.h>
+#include <pulsecore/core-util.h>
+
+int main(int argc, char *argv[]) {
+ void *p;
+ int fd;
+ pa_memtrap *m;
+
+ pa_log_set_level(PA_LOG_DEBUG);
+ pa_memtrap_install();
+
+ /* Create the memory map */
+ pa_assert_se((fd = open("sigbus-test-map", O_RDWR|O_TRUNC|O_CREAT, 0660)) >= 0);
+ pa_assert_se(unlink("sigbus-test-map") == 0);
+ pa_assert_se(ftruncate(fd, PA_PAGE_SIZE) >= 0);
+ pa_assert_se((p = mmap(NULL, PA_PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) != MAP_FAILED);
+
+ /* Register memory map */
+ m = pa_memtrap_add(p, PA_PAGE_SIZE);
+
+ /* Use memory map */
+ pa_snprintf(p, PA_PAGE_SIZE, "This is a test that should work fine.");
+
+ /* Verify memory map */
+ pa_log("Let's see if this worked: %s", (char*) p);
+ pa_log("And memtrap says it is good: %s", pa_yes_no(pa_memtrap_is_good(m)));
+
+ /* Invalidate mapping */
+ pa_assert_se(ftruncate(fd, 0) >= 0);
+
+ /* Use memory map */
+ pa_snprintf(p, PA_PAGE_SIZE, "This is a test that should fail but get caught.");
+
+ /* Verify memory map */
+ pa_log("Let's see if this worked: %s", (char*) p);
+ pa_log("And memtrap says it is good: %s", pa_yes_no(pa_memtrap_is_good(m)));
+
+ pa_memtrap_remove(m);
+ munmap(p, PA_PAGE_SIZE);
+
+ return 0;
+}
diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
new file mode 100644
index 00000000..2cc9f58b
--- /dev/null
+++ b/src/tests/smoother-test.c
@@ -0,0 +1,82 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <pulsecore/time-smoother.h>
+#include <pulse/timeval.h>
+
+int main(int argc, char*argv[]) {
+ pa_usec_t x;
+ unsigned u = 0;
+ pa_smoother *s;
+ int m;
+
+/* unsigned msec[] = { */
+/* 200, 200, */
+/* 300, 320, */
+/* 400, 400, */
+/* 500, 480, */
+/* 0, 0 */
+/* }; */
+
+ int msec[200];
+
+ srand(0);
+
+ pa_log_set_level(PA_LOG_DEBUG);
+
+ for (m = 0, u = 0; u < PA_ELEMENTSOF(msec); u+= 2) {
+
+ msec[u] = m+1 + (rand() % 100) - 50;
+ msec[u+1] = m + (rand() % 2000) - 1000 + 5000;
+
+ m += rand() % 100;
+
+ if (msec[u] < 0)
+ msec[u] = 0;
+
+ if (msec[u+1] < 0)
+ msec[u+1] = 0;
+ }
+
+ s = pa_smoother_new(700*PA_USEC_PER_MSEC, 2000*PA_USEC_PER_MSEC, FALSE, TRUE, 6, 0, TRUE);
+
+ for (x = 0, u = 0; x < PA_USEC_PER_SEC * 10; x += PA_USEC_PER_MSEC) {
+
+ while (u < PA_ELEMENTSOF(msec) && (pa_usec_t) msec[u]*PA_USEC_PER_MSEC < x) {
+ pa_smoother_put(s, (pa_usec_t) msec[u] * PA_USEC_PER_MSEC, (pa_usec_t) msec[u+1] * PA_USEC_PER_MSEC);
+ printf("%i\t\t%i\n", msec[u], msec[u+1]);
+ u += 2;
+
+ pa_smoother_resume(s, (pa_usec_t) msec[u] * PA_USEC_PER_MSEC, TRUE);
+ }
+
+ printf("%llu\t%llu\n", (unsigned long long) (x/PA_USEC_PER_MSEC), (unsigned long long) (pa_smoother_get(s, x)/PA_USEC_PER_MSEC));
+ }
+
+ pa_smoother_free(s);
+
+ return 0;
+}
diff --git a/src/tests/stripnul.c b/src/tests/stripnul.c
new file mode 100644
index 00000000..d677ad20
--- /dev/null
+++ b/src/tests/stripnul.c
@@ -0,0 +1,70 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+
+int main(int argc, char *argv[]) {
+ FILE *i, *o;
+ size_t granularity;
+ pa_bool_t found = FALSE;
+ uint8_t *zero;
+
+ pa_assert_se(argc >= 2);
+ pa_assert_se((granularity = (size_t) atoi(argv[1])) >= 1);
+ pa_assert_se((i = (argc >= 3) ? fopen(argv[2], "r") : stdin));
+ pa_assert_se((o = (argc >= 4) ? fopen(argv[3], "w") : stdout));
+
+ zero = pa_xmalloc0(granularity);
+
+ for (;;) {
+ uint8_t buffer[16*1024], *p;
+ size_t k;
+
+ k = fread(buffer, granularity, sizeof(buffer)/granularity, i);
+
+ if (k <= 0)
+ break;
+
+ if (found)
+ pa_assert_se(fwrite(buffer, granularity, k, o) == k);
+ else {
+ for (p = buffer; ((size_t) (p-buffer)/granularity) < k; p += granularity)
+ if (memcmp(p, zero, granularity)) {
+ size_t left;
+ found = TRUE;
+ left = (size_t) (k - (size_t) (p-buffer)/granularity);
+ pa_assert_se(fwrite(p, granularity, left, o) == left);
+ break;
+ }
+ }
+ }
+
+ fflush(o);
+
+ return 0;
+}
diff --git a/src/tests/strlist-test.c b/src/tests/strlist-test.c
index 4262a001..86f4f075 100644
--- a/src/tests/strlist-test.c
+++ b/src/tests/strlist-test.c
@@ -1,10 +1,10 @@
#include <stdio.h>
#include <pulse/xmalloc.h>
+
#include <pulsecore/strlist.h>
-#include <pulsecore/gccmacro.h>
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) {
+int main(int argc, char* argv[]) {
char *t, *u;
pa_strlist *l = NULL;
@@ -16,7 +16,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) {
t = pa_strlist_tostring(l);
pa_strlist_free(l);
-
+
fprintf(stderr, "1: %s\n", t);
l = pa_strlist_parse(t);
@@ -29,9 +29,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) {
l = pa_strlist_pop(l, &u);
fprintf(stderr, "3: %s\n", u);
pa_xfree(u);
-
+
l = pa_strlist_remove(l, "c");
-
+
t = pa_strlist_tostring(l);
fprintf(stderr, "4: %s\n", t);
pa_xfree(t);
diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c
index 39c6aac4..8eaa25fe 100644
--- a/src/tests/sync-playback.c
+++ b/src/tests/sync-playback.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -24,13 +22,11 @@
#endif
#include <signal.h>
-#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
-#include <getopt.h>
#include <math.h>
#include <pulse/pulseaudio.h>
@@ -56,9 +52,10 @@ static const pa_sample_spec sample_spec = {
static const pa_buffer_attr buffer_attr = {
.maxlength = SAMPLE_HZ*sizeof(float)*NSTREAMS, /* exactly space for the entire play time */
- .tlength = 0,
+ .tlength = (uint32_t) -1,
.prebuf = 0, /* Setting prebuf to 0 guarantees us the the streams will run synchronously, no matter what */
- .minreq = 0
+ .minreq = (uint32_t) -1,
+ .fragsize = 0
};
static void nop_free_cb(void *p) {}
@@ -67,7 +64,7 @@ static void underflow_cb(struct pa_stream *s, void *userdata) {
int i = (int) (long) userdata;
fprintf(stderr, "Stream %i finished\n", i);
-
+
if (++n_streams_ready >= 2*NSTREAMS) {
fprintf(stderr, "We're done\n");
mainloop_api->quit(mainloop_api, 0);
@@ -89,19 +86,19 @@ static void stream_state_callback(pa_stream *s, void *userdata) {
int r, i = (int) (long) userdata;
fprintf(stderr, "Writing data to stream %i.\n", i);
-
- r = pa_stream_write(s, data, sizeof(data), nop_free_cb, sizeof(data) * i, PA_SEEK_ABSOLUTE);
+
+ r = pa_stream_write(s, data, sizeof(data), nop_free_cb, (int64_t) sizeof(data) * (int64_t) i, PA_SEEK_ABSOLUTE);
assert(r == 0);
/* Be notified when this stream is drained */
pa_stream_set_underflow_callback(s, underflow_cb, userdata);
-
+
/* All streams have been set up, let's go! */
if (++n_streams_ready >= NSTREAMS) {
fprintf(stderr, "Uncorking\n");
pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL));
}
-
+
break;
}
@@ -121,7 +118,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
-
+
case PA_CONTEXT_READY: {
int i;
@@ -131,18 +128,18 @@ static void context_state_callback(pa_context *c, void *userdata) {
char name[64];
fprintf(stderr, "Creating stream %i\n", i);
-
+
snprintf(name, sizeof(name), "stream #%i", i);
-
+
streams[i] = pa_stream_new(c, name, &sample_spec, NULL);
assert(streams[i]);
pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i);
pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]);
}
-
+
break;
}
-
+
case PA_CONTEXT_TERMINATED:
mainloop_api->quit(mainloop_api, 0);
break;
@@ -163,7 +160,7 @@ int main(int argc, char *argv[]) {
for (i = 0; i < NSTREAMS; i++)
streams[i] = NULL;
-
+
/* Set up a new main loop */
m = pa_mainloop_new();
assert(m);
@@ -175,11 +172,16 @@ int main(int argc, char *argv[]) {
pa_context_set_state_callback(context, context_state_callback, NULL);
- pa_context_connect(context, NULL, 0, NULL);
+ /* Connect the context */
+ if (pa_context_connect(context, NULL, 0, NULL) < 0) {
+ fprintf(stderr, "pa_context_connect() failed.\n");
+ goto quit;
+ }
if (pa_mainloop_run(m, &ret) < 0)
fprintf(stderr, "pa_mainloop_run() failed.\n");
+quit:
pa_context_unref(context);
for (i = 0; i < NSTREAMS; i++)
@@ -187,6 +189,6 @@ int main(int argc, char *argv[]) {
pa_stream_unref(streams[i]);
pa_mainloop_free(m);
-
+
return ret;
}
diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c
index bf3d4cd2..72275972 100644
--- a/src/tests/thread-mainloop-test.c
+++ b/src/tests/thread-mainloop-test.c
@@ -1,18 +1,16 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@@ -23,49 +21,49 @@
#include <config.h>
#endif
-#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <pulse/rtclock.h>
#include <pulse/timeval.h>
#include <pulse/util.h>
-
-#include <pulsecore/gccmacro.h>
#include <pulse/thread-mainloop.h>
-static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
+#include <pulsecore/macro.h>
+#include <pulsecore/core-rtclock.h>
+
+static void tcb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata) {
+ pa_assert_se(pa_threaded_mainloop_in_thread(userdata));
fprintf(stderr, "TIME EVENT START\n");
pa_threaded_mainloop_signal(userdata, 1);
fprintf(stderr, "TIME EVENT END\n");
}
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
+int main(int argc, char *argv[]) {
pa_mainloop_api *a;
pa_threaded_mainloop *m;
struct timeval tv;
- m = pa_threaded_mainloop_new();
- assert(m);
- a = pa_threaded_mainloop_get_api(m);
- assert(a);
+ pa_assert_se(m = pa_threaded_mainloop_new());
+ pa_assert_se(a = pa_threaded_mainloop_get_api(m));
- pa_threaded_mainloop_start(m);
+ pa_assert_se(pa_threaded_mainloop_start(m) >= 0);
pa_threaded_mainloop_lock(m);
-
- pa_gettimeofday(&tv);
- tv.tv_sec += 5;
- a->time_new(a, &tv, tcb, m);
-
+
+ pa_assert_se(!pa_threaded_mainloop_in_thread(m));
+
+ a->time_new(a, pa_timeval_rtstore(&tv, pa_rtclock_now() + 5 * PA_USEC_PER_SEC, TRUE), tcb, m);
+
fprintf(stderr, "waiting 5s (signal)\n");
pa_threaded_mainloop_wait(m);
fprintf(stderr, "wait completed\n");
pa_threaded_mainloop_accept(m);
fprintf(stderr, "signal accepted\n");
-
+
pa_threaded_mainloop_unlock(m);
-
+
fprintf(stderr, "waiting 5s (sleep)\n");
pa_msleep(5000);
diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c
new file mode 100644
index 00000000..4071e429
--- /dev/null
+++ b/src/tests/thread-test.c
@@ -0,0 +1,140 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/thread.h>
+#include <pulsecore/mutex.h>
+#include <pulsecore/once.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+#include <pulse/xmalloc.h>
+
+static pa_mutex *mutex = NULL;
+static pa_cond *cond1 = NULL, *cond2 = NULL;
+static pa_tls *tls = NULL;
+
+static int magic_number = 0;
+
+#define THREADS_MAX 20
+
+static void once_func(void) {
+ pa_log("once!");
+}
+
+static pa_once once = PA_ONCE_INIT;
+
+static void thread_func(void *data) {
+ pa_tls_set(tls, data);
+
+ pa_log("thread_func() for %s starting...", (char*) pa_tls_get(tls));
+
+ pa_mutex_lock(mutex);
+
+ for (;;) {
+ int k, n;
+
+ pa_log("%s waiting ...", (char*) pa_tls_get(tls));
+
+ for (;;) {
+
+ if (magic_number < 0)
+ goto quit;
+
+ if (magic_number != 0)
+ break;
+
+ pa_cond_wait(cond1, mutex);
+ }
+
+ k = magic_number;
+ magic_number = 0;
+
+ pa_mutex_unlock(mutex);
+
+ pa_run_once(&once, once_func);
+
+ pa_cond_signal(cond2, 0);
+
+ pa_log("%s got number %i", (char*) pa_tls_get(tls), k);
+
+ /* Spin! */
+ for (n = 0; n < k; n++)
+ pa_thread_yield();
+
+ pa_mutex_lock(mutex);
+ }
+
+quit:
+
+ pa_mutex_unlock(mutex);
+
+ pa_log("thread_func() for %s done...", (char*) pa_tls_get(tls));
+}
+
+int main(int argc, char *argv[]) {
+ int i, k;
+ pa_thread* t[THREADS_MAX];
+
+ mutex = pa_mutex_new(FALSE, FALSE);
+ cond1 = pa_cond_new();
+ cond2 = pa_cond_new();
+ tls = pa_tls_new(pa_xfree);
+
+ for (i = 0; i < THREADS_MAX; i++) {
+ t[i] = pa_thread_new("test", thread_func, pa_sprintf_malloc("Thread #%i", i+1));
+ assert(t[i]);
+ }
+
+ pa_mutex_lock(mutex);
+
+ pa_log("loop-init");
+
+ for (k = 0; k < 100; k++) {
+ assert(magic_number == 0);
+
+
+ magic_number = (int) rand() % 0x10000;
+
+ pa_log("iteration %i (%i)", k, magic_number);
+
+ pa_cond_signal(cond1, 0);
+
+ pa_cond_wait(cond2, mutex);
+ }
+
+ pa_log("loop-exit");
+
+ magic_number = -1;
+ pa_cond_signal(cond1, 1);
+
+ pa_mutex_unlock(mutex);
+
+ for (i = 0; i < THREADS_MAX; i++)
+ pa_thread_free(t[i]);
+
+ pa_mutex_free(mutex);
+ pa_cond_free(cond1);
+ pa_cond_free(cond2);
+ pa_tls_free(tls);
+
+ return 0;
+}
diff --git a/src/tests/usergroup-test.c b/src/tests/usergroup-test.c
new file mode 100644
index 00000000..3948e0f8
--- /dev/null
+++ b/src/tests/usergroup-test.c
@@ -0,0 +1,155 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2009 Ted Percival
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+
+#include <pulsecore/usergroup.h>
+
+static int load_reference_structs(struct group **gr, struct passwd **pw) {
+ setpwent();
+ *pw = getpwent();
+ endpwent();
+
+ setgrent();
+ *gr = getgrent();
+ endgrent();
+
+ return (*gr && *pw) ? 0 : 1;
+}
+
+static int compare_group(const struct group *a, const struct group *b) {
+ char **amem, **bmem;
+
+ if (strcmp(a->gr_name, b->gr_name)) {
+ fprintf(stderr, "Group name mismatch: [%s] [%s]\n", a->gr_name, b->gr_name);
+ return 1;
+ }
+
+ if (strcmp(a->gr_passwd, b->gr_passwd)) {
+ fprintf(stderr, "Group password mismatch: [%s] [%s]\n", a->gr_passwd, b->gr_passwd);
+ return 1;
+ }
+
+ if (a->gr_gid != b->gr_gid) {
+ fprintf(stderr, "Gid mismatch: [%lu] [%lu]\n", (unsigned long) a->gr_gid, (unsigned long) b->gr_gid);
+ return 1;
+ }
+
+ /* XXX: Assuming the group ordering is identical. */
+ for (amem = a->gr_mem, bmem = b->gr_mem; *amem && *bmem; ++amem, ++bmem) {
+ if (strcmp(*amem, *bmem)) {
+ fprintf(stderr, "Group member mismatch: [%s] [%s]\n", *amem, *bmem);
+ return 1;
+ }
+ }
+
+ if (*amem || *bmem) {
+ fprintf(stderr, "Mismatched group count\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int compare_passwd(const struct passwd *a, const struct passwd *b) {
+ if (strcmp(a->pw_name, b->pw_name)) {
+ fprintf(stderr, "pw_name mismatch: [%s] [%s]\n", a->pw_name, b->pw_name);
+ return 1;
+ }
+
+ if (strcmp(a->pw_passwd, b->pw_passwd)) {
+ fprintf(stderr, "pw_passwd mismatch: [%s] [%s]\n", a->pw_passwd, b->pw_passwd);
+ return 1;
+ }
+
+ if (a->pw_uid != b->pw_uid) {
+ fprintf(stderr, "pw_uid mismatch: [%lu] [%lu]\n", (unsigned long) a->pw_uid, (unsigned long) b->pw_uid);
+ return 1;
+ }
+
+ if (a->pw_gid != b->pw_gid) {
+ fprintf(stderr, "pw_gid mismatch: [%lu] [%lu]\n", (unsigned long) a->pw_gid, (unsigned long) b->pw_gid);
+ return 1;
+ }
+
+ if (strcmp(a->pw_gecos, b->pw_gecos)) {
+ fprintf(stderr, "pw_gecos mismatch: [%s] [%s]\n", a->pw_gecos, b->pw_gecos);
+ return 1;
+ }
+
+ if (strcmp(a->pw_dir, b->pw_dir)) {
+ fprintf(stderr, "pw_dir mismatch: [%s] [%s]\n", a->pw_dir, b->pw_dir);
+ return 1;
+ }
+
+ if (strcmp(a->pw_shell, b->pw_shell)) {
+ fprintf(stderr, "pw_shell mismatch: [%s] [%s]\n", a->pw_shell, b->pw_shell);
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ struct group *gr;
+ struct passwd *pw;
+ int err;
+ struct group *reference_group = NULL;
+ struct passwd *reference_passwd = NULL;
+
+ err = load_reference_structs(&reference_group, &reference_passwd);
+ if (err)
+ return 77;
+
+ errno = 0;
+ gr = pa_getgrgid_malloc(reference_group->gr_gid);
+ if (compare_group(reference_group, gr))
+ return 1;
+ pa_getgrgid_free(gr);
+
+ errno = 0;
+ gr = pa_getgrnam_malloc(reference_group->gr_name);
+ if (compare_group(reference_group, gr))
+ return 1;
+ pa_getgrnam_free(gr);
+
+ errno = 0;
+ pw = pa_getpwuid_malloc(reference_passwd->pw_uid);
+ if (compare_passwd(reference_passwd, pw))
+ return 1;
+ pa_getpwuid_free(pw);
+
+ errno = 0;
+ pw = pa_getpwnam_malloc(reference_passwd->pw_name);
+ if (compare_passwd(reference_passwd, pw))
+ return 1;
+ pa_getpwnam_free(pw);
+
+ return 0;
+}
diff --git a/src/tests/utf8-test.c b/src/tests/utf8-test.c
index 2e9f128a..f1708ad4 100644
--- a/src/tests/utf8-test.c
+++ b/src/tests/utf8-test.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
#include <stdio.h>
#include <assert.h>
@@ -8,13 +6,13 @@
int main(int argc, char *argv[]) {
char *c;
-
+
assert(pa_utf8_valid("hallo"));
assert(pa_utf8_valid("hallo\n"));
assert(!pa_utf8_valid("hüpfburg\n"));
assert(pa_utf8_valid("hallo\n"));
assert(pa_utf8_valid("hüpfburg\n"));
-
+
printf("LATIN1: %s\n", c = pa_utf8_filter("hüpfburg"));
pa_xfree(c);
printf("UTF8: %sx\n", c = pa_utf8_filter("hüpfburg"));
diff --git a/src/tests/vector-test.c b/src/tests/vector-test.c
new file mode 100644
index 00000000..7494348c
--- /dev/null
+++ b/src/tests/vector-test.c
@@ -0,0 +1,83 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2009 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/vector.h>
+#include <pulsecore/log.h>
+
+int main(int argc, char *argv[]) {
+
+#ifdef __SSE2__
+ pa_int16_vector_t input, zero;
+ pa_int32_vector_t unpacked1, unpacked2;
+ pa_int32_vector_t volume1, volume2, volume1_hi, volume1_lo, volume2_hi, volume2_lo, reduce, mask;
+ pa_int16_vector_t output;
+
+ unsigned u;
+
+ zero.v = PA_INT16_VECTOR_MAKE(0);
+ reduce.v = PA_INT32_VECTOR_MAKE(0x10000);
+ volume1.v = volume2.v = PA_INT32_VECTOR_MAKE(0x10000*2+7);
+ mask.v = PA_INT32_VECTOR_MAKE(0xFFFF);
+
+ volume1_lo.m = _mm_and_si128(volume1.m, mask.m);
+ volume2_lo.m = _mm_and_si128(volume2.m, mask.m);
+ volume1_hi.m = _mm_srli_epi32(volume1.m, 16);
+ volume2_hi.m = _mm_srli_epi32(volume2.m, 16);
+
+ input.v = PA_INT16_VECTOR_MAKE(32000);
+
+ for (u = 0; u < PA_INT16_VECTOR_SIZE; u++)
+ pa_log("input=%i\n", input.i[u]);
+
+ unpacked1.m = _mm_unpackhi_epi16(zero.m, input.m);
+ unpacked2.m = _mm_unpacklo_epi16(zero.m, input.m);
+
+ for (u = 0; u < PA_INT32_VECTOR_SIZE; u++)
+ pa_log("unpacked1=%i\n", unpacked1.i[u]);
+
+ unpacked1.v /= reduce.v;
+ unpacked2.v /= reduce.v;
+
+ for (u = 0; u < PA_INT32_VECTOR_SIZE; u++)
+ pa_log("unpacked1=%i\n", unpacked1.i[u]);
+
+ for (u = 0; u < PA_INT32_VECTOR_SIZE; u++)
+ pa_log("volume1=%i\n", volume1.i[u]);
+
+ unpacked1.v = (unpacked1.v * volume1_lo.v) / reduce.v + unpacked1.v * volume1_hi.v;
+ unpacked2.v = (unpacked2.v * volume2_lo.v) / reduce.v + unpacked2.v * volume2_hi.v;
+
+ for (u = 0; u < PA_INT32_VECTOR_SIZE; u++)
+ pa_log("unpacked1=%i\n", unpacked1.i[u]);
+
+ output.m = _mm_packs_epi32(unpacked1.m, unpacked2.m);
+
+ for (u = 0; u < PA_INT16_VECTOR_SIZE; u++)
+ pa_log("output=%i\n", output.i[u]);
+
+#endif
+
+ return 0;
+}
diff --git a/src/tests/voltest.c b/src/tests/voltest.c
index 3de884af..ece86f85 100644
--- a/src/tests/voltest.c
+++ b/src/tests/voltest.c
@@ -1,22 +1,134 @@
-/* $Id$ */
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <stdio.h>
+#include <math.h>
#include <pulse/volume.h>
-#include <pulsecore/gccmacro.h>
-int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
+#include <pulsecore/macro.h>
+
+int main(int argc, char *argv[]) {
pa_volume_t v;
+ pa_cvolume cv;
+ float b;
+ pa_channel_map map;
+ pa_volume_t md = 0;
+ unsigned mdn = 0;
+
+ printf("Attenuation of sample 1 against 32767: %g dB\n", 20.0*log10(1.0/32767.0));
+ printf("Smallest possible attenutation > 0 applied to 32767: %li\n", lrint(32767.0*pa_sw_volume_to_linear(1)));
for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
double dB = pa_sw_volume_to_dB(v);
double f = pa_sw_volume_to_linear(v);
-
+
printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n",
v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f));
+ }
+
+ for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
+ char s[PA_CVOLUME_SNPRINT_MAX], t[PA_SW_CVOLUME_SNPRINT_DB_MAX];
+
+ pa_cvolume_set(&cv, 2, v);
+
+ printf("Volume: %3i [%s] [%s]\n",
+ v,
+ pa_cvolume_snprint(s, sizeof(s), &cv),
+ pa_sw_cvolume_snprint_dB(t, sizeof(t), &cv));
+
+ }
+
+ map.channels = cv.channels = 2;
+ map.map[0] = PA_CHANNEL_POSITION_LEFT;
+ map.map[1] = PA_CHANNEL_POSITION_RIGHT;
+ for (cv.values[0] = PA_VOLUME_MUTED; cv.values[0] <= PA_VOLUME_NORM*2; cv.values[0] += 4096)
+ for (cv.values[1] = PA_VOLUME_MUTED; cv.values[1] <= PA_VOLUME_NORM*2; cv.values[1] += 4096) {
+ char s[PA_CVOLUME_SNPRINT_MAX];
+
+ printf("Volume: [%s]; balance: %2.1f\n", pa_cvolume_snprint(s, sizeof(s), &cv), pa_cvolume_get_balance(&cv, &map));
+ }
+
+ for (cv.values[0] = PA_VOLUME_MUTED+4096; cv.values[0] <= PA_VOLUME_NORM*2; cv.values[0] += 4096)
+ for (cv.values[1] = PA_VOLUME_MUTED; cv.values[1] <= PA_VOLUME_NORM*2; cv.values[1] += 4096)
+ for (b = -1.0f; b <= 1.0f; b += 0.2f) {
+ char s[PA_CVOLUME_SNPRINT_MAX];
+ pa_cvolume r;
+ float k;
+
+ printf("Before: volume: [%s]; balance: %2.1f\n", pa_cvolume_snprint(s, sizeof(s), &cv), pa_cvolume_get_balance(&cv, &map));
+
+ r = cv;
+ pa_cvolume_set_balance(&r, &map,b);
+
+ k = pa_cvolume_get_balance(&r, &map);
+ printf("After: volume: [%s]; balance: %2.1f (intended: %2.1f) %s\n", pa_cvolume_snprint(s, sizeof(s), &r), k, b, k < b-.05 || k > b+.5 ? "MISMATCH" : "");
+ }
+
+ for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 51) {
+
+ double l = pa_sw_volume_to_linear(v);
+ pa_volume_t k = pa_sw_volume_from_linear(l);
+ double db = pa_sw_volume_to_dB(v);
+ pa_volume_t r = pa_sw_volume_from_dB(db);
+ pa_volume_t w;
+
+ pa_assert(k == v);
+ pa_assert(r == v);
+
+ for (w = PA_VOLUME_MUTED; w < PA_VOLUME_NORM*2; w += 37) {
+
+ double t = pa_sw_volume_to_linear(w);
+ double db2 = pa_sw_volume_to_dB(w);
+ pa_volume_t p, p1, p2;
+ double q, qq;
+
+ p = pa_sw_volume_multiply(v, w);
+ qq = db + db2;
+ p2 = pa_sw_volume_from_dB(qq);
+ q = l*t;
+ p1 = pa_sw_volume_from_linear(q);
+
+ if (p2 > p && p2 - p > md)
+ md = p2 - p;
+ if (p2 < p && p - p2 > md)
+ md = p - p2;
+ if (p1 > p && p1 - p > md)
+ md = p1 - p;
+ if (p1 < p && p - p1 > md)
+ md = p - p1;
+
+ if (p1 != p || p2 != p)
+ mdn++;
+ }
}
+ printf("max deviation: %lu n=%lu\n", (unsigned long) md, (unsigned long) mdn);
+
+ pa_assert(md <= 1);
+ pa_assert(mdn <= 251);
+
return 0;
}
diff --git a/src/tests/volume-ui.py b/src/tests/volume-ui.py
new file mode 100644
index 00000000..7909b801
--- /dev/null
+++ b/src/tests/volume-ui.py
@@ -0,0 +1,282 @@
+#!/usr/bin/python
+
+import pygtk, gtk, sys
+from ctypes import *
+
+try:
+ libpulse = cdll.LoadLibrary("../.libs/libpulse.so")
+except OSError:
+ try:
+ libpulse = cdll.LoadLibrary(".libs/libpulse.so")
+ except OSError:
+ libpulse = cdll.LoadLibrary("libpulse.so")
+
+class ChannelMap(Structure):
+ _fields_ = [("channels", c_ubyte),
+ ("map", c_uint * 32)]
+
+ _to_name = libpulse.pa_channel_map_to_name
+ _to_name.restype = c_char_p
+ _to_name.argtypes = [c_void_p]
+
+ _to_pretty_name = libpulse.pa_channel_map_to_pretty_name
+ _to_pretty_name.restype = c_char_p
+ _to_pretty_name.argtypes = [c_void_p]
+
+ _snprint = libpulse.pa_channel_map_snprint
+ _snprint.restype = c_char_p
+ _snprint.argtypes = [c_char_p, c_ulong, c_void_p]
+
+ _position_to_string = libpulse.pa_channel_position_to_string
+ _position_to_string.restype = c_char_p
+ _position_to_string.argtypes = [c_uint]
+
+ _position_to_pretty_string = libpulse.pa_channel_position_to_pretty_string
+ _position_to_pretty_string.restype = c_char_p
+ _position_to_pretty_string.argtypes = [c_uint]
+
+ _can_balance = libpulse.pa_channel_map_can_balance
+ _can_balance.restype = c_int
+ _can_balance.argtypes = [c_void_p]
+
+ _can_fade = libpulse.pa_channel_map_can_fade
+ _can_fade.restype = c_int
+ _can_fade.argtypes = [c_void_p]
+
+ _parse = libpulse.pa_channel_map_parse
+ _parse.restype = c_void_p
+ _parse.argtypes = [c_void_p, c_char_p]
+
+ def to_name(this):
+ return this._to_name(byref(this))
+
+ def to_pretty_name(this):
+ return this._to_pretty_name(byref(this))
+
+ def snprint(this):
+ s = create_string_buffer(336)
+ r = this._snprint(s, len(s), byref(this))
+
+ if r is None:
+ return None
+ else:
+ return s.value
+
+ def position_to_string(this, pos):
+ return this._position_to_string(pos)
+
+ def position_to_pretty_string(this, pos):
+ return this._position_to_pretty_string(pos)
+
+ def can_balance(this):
+ return bool(this._can_balance(byref(this)))
+
+ def can_fade(this):
+ return bool(this._can_fade(byref(this)))
+
+ def parse(this, s):
+ if this._parse(byref(this), s) is None:
+ raise Exception("Parse failure")
+
+
+class CVolume(Structure):
+ _fields_ = [("channels", c_ubyte),
+ ("values", c_uint32 * 32)]
+
+ _snprint = libpulse.pa_cvolume_snprint
+ _snprint.restype = c_char_p
+ _snprint.argtypes = [c_char_p, c_ulong, c_void_p]
+
+ _max = libpulse.pa_cvolume_max
+ _max.restype = c_uint32
+ _max.argtypes = [c_void_p]
+
+ _scale = libpulse.pa_cvolume_scale
+ _scale.restype = c_void_p
+ _scale.argtypes = [c_void_p, c_uint32]
+
+ _get_balance = libpulse.pa_cvolume_get_balance
+ _get_balance.restype = c_float
+ _get_balance.argtypes = [c_void_p, c_void_p]
+
+ _get_fade = libpulse.pa_cvolume_get_fade
+ _get_fade.restype = c_float
+ _get_fade.argtypes = [c_void_p, c_void_p]
+
+ _set_balance = libpulse.pa_cvolume_set_balance
+ _set_balance.restype = c_void_p
+ _set_balance.argtypes = [c_void_p, c_void_p, c_float]
+
+ _set_fade = libpulse.pa_cvolume_set_fade
+ _set_fade.restype = c_void_p
+ _set_fade.argtypes = [c_void_p, c_void_p, c_float]
+
+ _to_dB = libpulse.pa_sw_volume_to_dB
+ _to_dB.restype = c_double
+ _to_dB.argytpes = [c_uint32]
+
+ def snprint(this):
+ s = create_string_buffer(320)
+ r = this._snprint(s, len(s), byref(this))
+
+ if r is None:
+ return None
+ else:
+ return s.raw
+
+ def max(this):
+ return this._max(byref(this))
+
+ def scale(this, v):
+ return this._scale(byref(this), v)
+
+ def get_balance(this, cm):
+ return this._get_balance(byref(this), byref(cm))
+
+ def get_fade(this, cm):
+ return this._get_fade(byref(this), byref(cm))
+
+ def set_balance(this, cm, f):
+ return this._set_balance(byref(this), byref(cm), f)
+
+ def set_fade(this, cm, f):
+ return this._set_fade(byref(this), byref(cm), f)
+
+ def to_dB(this, channel = None):
+ if channel is None:
+ return this._to_dB(this.max())
+
+ return this._to_dB(this.values[channel])
+
+cm = ChannelMap()
+
+if len(sys.argv) > 1:
+ cm.parse(sys.argv[1])
+else:
+ cm.parse("surround-51")
+
+v = CVolume()
+v.channels = cm.channels
+
+for i in range(cm.channels):
+ v.values[i] = 65536
+
+title = cm.to_pretty_name()
+if title is None:
+ title = cm.snprint()
+
+window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+window.set_title(unicode(title))
+window.set_border_width(12)
+
+vbox = gtk.VBox(spacing=6)
+
+channel_labels = {}
+channel_scales = {}
+channel_dB_labels = {}
+
+def update_volume(update_channels = True, update_fade = True, update_balance = True, update_scale = True):
+ if update_channels:
+ for i in range(cm.channels):
+ channel_scales[i].set_value(v.values[i])
+
+ if update_scale:
+ value_scale.set_value(v.max())
+
+ if update_balance:
+ balance_scale.set_value(v.get_balance(cm))
+
+ if update_fade:
+ fade_scale.set_value(v.get_fade(cm))
+
+ for i in range(cm.channels):
+ channel_dB_labels[i].set_label("%0.2f dB" % v.to_dB(i))
+
+ value_dB_label.set_label("%0.2f dB" % v.to_dB())
+
+def fade_value_changed(fs):
+ v.set_fade(cm, fade_scale.get_value())
+ update_volume(update_fade = False)
+
+def balance_value_changed(fs):
+ v.set_balance(cm, balance_scale.get_value())
+ update_volume(update_balance = False)
+
+def value_value_changed(fs):
+ v.scale(int(value_scale.get_value()))
+ update_volume(update_scale = False)
+
+def channel_value_changed(fs, i):
+ v.values[i] = int(channel_scales[i].get_value())
+ update_volume(update_channels = False)
+
+for i in range(cm.channels):
+ channel_labels[i] = gtk.Label(cm.position_to_pretty_string(cm.map[i]))
+ channel_labels[i].set_alignment(0, 1)
+ vbox.pack_start(channel_labels[i], expand=False, fill=True)
+
+ channel_scales[i] = gtk.HScale()
+ channel_scales[i].set_range(0, 65536*3/2)
+ channel_scales[i].set_digits(0)
+ channel_scales[i].set_value_pos(gtk.POS_RIGHT)
+ vbox.pack_start(channel_scales[i], expand=False, fill=True)
+
+ channel_dB_labels[i] = gtk.Label("-xxx dB")
+ channel_dB_labels[i].set_alignment(1, 1)
+ vbox.pack_start(channel_dB_labels[i], expand=False, fill=True)
+
+value_label = gtk.Label("Value")
+value_label.set_alignment(0, .5)
+vbox.pack_start(value_label, expand=False, fill=True)
+value_scale = gtk.HScale()
+value_scale.set_range(0, 65536*3/2)
+value_scale.set_value_pos(gtk.POS_RIGHT)
+value_scale.set_digits(0)
+vbox.pack_start(value_scale, expand=False, fill=True)
+value_dB_label = gtk.Label("-xxx dB")
+value_dB_label.set_alignment(1, 1)
+vbox.pack_start(value_dB_label, expand=False, fill=True)
+
+balance_label = gtk.Label("Balance")
+balance_label.set_alignment(0, .5)
+vbox.pack_start(balance_label, expand=False, fill=True)
+balance_scale = gtk.HScale()
+balance_scale.set_range(-1.0, +1.0)
+balance_scale.set_value_pos(gtk.POS_RIGHT)
+balance_scale.set_digits(2)
+vbox.pack_start(balance_scale, expand=False, fill=True)
+
+fade_label = gtk.Label("Fade")
+fade_label.set_alignment(0, .5)
+vbox.pack_start(fade_label, expand=False, fill=True)
+fade_scale = gtk.HScale()
+fade_scale.set_range(-1.0, +1.0)
+fade_scale.set_value_pos(gtk.POS_RIGHT)
+fade_scale.set_digits(2)
+vbox.pack_start(fade_scale, expand=False, fill=True)
+
+window.add(vbox)
+window.set_default_size(600, 50)
+
+update_volume()
+
+for i in range(cm.channels):
+ channel_scales[i].connect("value_changed", channel_value_changed, i)
+fade_scale.connect("value_changed", fade_value_changed)
+balance_scale.connect("value_changed", balance_value_changed)
+value_scale.connect("value_changed", value_value_changed)
+
+vbox.show_all()
+
+if not cm.can_balance():
+ balance_label.hide()
+ balance_scale.hide()
+
+if not cm.can_fade():
+ fade_label.hide()
+ fade_scale.hide()
+
+
+window.show()
+
+gtk.main()