From 1160cad9c3f87659e810ebdb9c4a20626e8a4eed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Jul 2009 18:44:26 +0200 Subject: alsa: control 'Speaker' element as well --- src/modules/alsa/mixer/paths/analog-output-headphones.conf | 4 ++++ src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf | 6 ++++++ src/modules/alsa/mixer/paths/analog-output-mono.conf | 6 ++++++ src/modules/alsa/mixer/paths/analog-output.conf | 6 ++++++ 4 files changed, 22 insertions(+) diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf index c018e0eb..691cb3f2 100644 --- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf +++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf @@ -44,6 +44,10 @@ volume = merge override-map.1 = all override-map.2 = all-left,all-right +[Element Speaker] +switch = off +volume = off + [Element Front] switch = off volume = off diff --git a/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf b/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf index 7a267890..2db976a5 100644 --- a/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf +++ b/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf @@ -45,6 +45,12 @@ override-map.2 = lfe,lfe switch = off volume = off +[Element Speaker] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + [Element Front] switch = off volume = off diff --git a/src/modules/alsa/mixer/paths/analog-output-mono.conf b/src/modules/alsa/mixer/paths/analog-output-mono.conf index f6cb9f8a..a58cc970 100644 --- a/src/modules/alsa/mixer/paths/analog-output-mono.conf +++ b/src/modules/alsa/mixer/paths/analog-output-mono.conf @@ -42,6 +42,12 @@ override-map.2 = all-left,all-right switch = off volume = off +[Element Speaker] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + [Element Front] switch = off volume = off diff --git a/src/modules/alsa/mixer/paths/analog-output.conf b/src/modules/alsa/mixer/paths/analog-output.conf index ea108aaf..b412a437 100644 --- a/src/modules/alsa/mixer/paths/analog-output.conf +++ b/src/modules/alsa/mixer/paths/analog-output.conf @@ -41,6 +41,12 @@ volume = off switch = off volume = off +[Element Speaker] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + [Element Front] switch = mute volume = merge -- cgit From ac38c4d89845237cd5d19c29d8d3ef55f0374dca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Jul 2009 18:49:28 +0200 Subject: build-sys: add a couple of stub Makefiles --- src/modules/alsa/mixer/Makefile | 1 + src/modules/alsa/mixer/paths/Makefile | 1 + src/modules/alsa/mixer/profile-sets/Makefile | 1 + 3 files changed, 3 insertions(+) create mode 120000 src/modules/alsa/mixer/Makefile create mode 120000 src/modules/alsa/mixer/paths/Makefile create mode 120000 src/modules/alsa/mixer/profile-sets/Makefile diff --git a/src/modules/alsa/mixer/Makefile b/src/modules/alsa/mixer/Makefile new file mode 120000 index 00000000..b4955194 --- /dev/null +++ b/src/modules/alsa/mixer/Makefile @@ -0,0 +1 @@ +../../../pulse/Makefile \ No newline at end of file diff --git a/src/modules/alsa/mixer/paths/Makefile b/src/modules/alsa/mixer/paths/Makefile new file mode 120000 index 00000000..dc23aaa2 --- /dev/null +++ b/src/modules/alsa/mixer/paths/Makefile @@ -0,0 +1 @@ +../../../../pulse/Makefile \ No newline at end of file diff --git a/src/modules/alsa/mixer/profile-sets/Makefile b/src/modules/alsa/mixer/profile-sets/Makefile new file mode 120000 index 00000000..dc23aaa2 --- /dev/null +++ b/src/modules/alsa/mixer/profile-sets/Makefile @@ -0,0 +1 @@ +../../../../pulse/Makefile \ No newline at end of file -- cgit From 5a0ef5fd139151b285720f2c9edf3b559556c86d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Jul 2009 19:12:53 +0200 Subject: daemon: replace colons by dash in per-machine directory names for compat with weird filesystems --- src/pulsecore/core-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 04e7eb24..5f777d5b 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -1481,7 +1481,7 @@ char *pa_get_runtime_dir(void) { goto fail; } - k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:runtime", d, mid); + k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid); pa_xfree(d); pa_xfree(mid); @@ -1904,7 +1904,7 @@ static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) { return NULL; } - r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:%s", rtp, mid, fn); + r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn); pa_xfree(mid); } else r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn); -- cgit From c325b93c01c5973db659aead6b66f753aa719168 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Jul 2009 19:24:26 +0200 Subject: alsa: don't reset volume/mute when selecting path --- src/modules/alsa/alsa-mixer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index a5515e1b..6a0b4ab7 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -940,7 +940,6 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { PA_LLIST_FOREACH(e, p->elements) { switch (e->switch_use) { - case PA_ALSA_SWITCH_MUTE: case PA_ALSA_SWITCH_OFF: r = element_set_switch(e, m, FALSE); break; @@ -949,6 +948,7 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { r = element_set_switch(e, m, TRUE); break; + case PA_ALSA_SWITCH_MUTE: case PA_ALSA_SWITCH_IGNORE: case PA_ALSA_SWITCH_SELECT: r = 0; @@ -960,7 +960,6 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { switch (e->volume_use) { case PA_ALSA_VOLUME_OFF: - case PA_ALSA_VOLUME_MERGE: r = element_mute_volume(e, m); break; @@ -968,6 +967,7 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { r = element_zero_volume(e, m); break; + case PA_ALSA_VOLUME_MERGE: case PA_ALSA_VOLUME_IGNORE: r = 0; break; -- cgit From e02e0259e5e0c22ff7fd598cfaf70f03e82c957a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Jul 2009 20:00:08 +0200 Subject: client: include zerocopy write calls in map file --- src/map-file | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/map-file b/src/map-file index a1d0a061..c6c8acca 100644 --- a/src/map-file +++ b/src/map-file @@ -219,6 +219,8 @@ pa_simple_get_latency; pa_simple_new; pa_simple_read; pa_simple_write; +pa_stream_begin_write; +pa_stream_cancel_write; pa_stream_connect_playback; pa_stream_connect_record; pa_stream_connect_upload; -- cgit From a81244a726b28fb7e3ccf5fd1d1d823023602c30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Jul 2009 20:01:40 +0200 Subject: pacat: use zero-copy write calls when playing audio file --- src/utils/pacat.c | 126 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index f00a32eb..9264a062 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -105,12 +105,12 @@ static void context_drain_complete(pa_context*c, void *userdata) { static void stream_drain_complete(pa_stream*s, int success, void *userdata) { if (!success) { - pa_log(_("Failed to drain stream: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("Failed to drain stream: %s"), pa_strerror(pa_context_errno(context))); quit(1); } if (verbose) - pa_log(_("Playback stream drained.\n")); + pa_log(_("Playback stream drained.")); pa_stream_disconnect(stream); pa_stream_unref(stream); @@ -120,7 +120,7 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { pa_context_disconnect(context); else { if (verbose) - pa_log(_("Draining connection to server.\n")); + pa_log(_("Draining connection to server.")); } } @@ -133,7 +133,7 @@ static void start_drain(void) { pa_stream_set_write_callback(stream, NULL, NULL); if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { - pa_log(_("pa_stream_drain(): %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("pa_stream_drain(): %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } @@ -156,7 +156,7 @@ static void do_stream_write(size_t length) { l = buffer_length; if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { - pa_log(_("pa_stream_write() failed: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("pa_stream_write() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } @@ -193,7 +193,11 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { pa_assert(sndfile); - data = pa_xmalloc(length); + if (pa_stream_begin_write(s, &data, &length) < 0) { + pa_log(_("pa_stream_begin_write() failed: %s"), pa_strerror(pa_context_errno(context))); + quit(1); + return; + } if (readf_function) { size_t k = pa_frame_size(&sample_spec); @@ -205,9 +209,9 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { bytes = sf_read_raw(sndfile, data, (sf_count_t) length); if (bytes > 0) - pa_stream_write(s, data, (size_t) bytes, pa_xfree, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, data, (size_t) bytes, NULL, 0, PA_SEEK_RELATIVE); else - pa_xfree(data); + pa_stream_cancel_write(s); if (bytes < (sf_count_t) length) start_drain(); @@ -226,12 +230,11 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); - while (pa_stream_readable_size(s) > 0) { const void *data; if (pa_stream_peek(s, &data, &length) < 0) { - pa_log(_("pa_stream_peek() failed: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } @@ -249,6 +252,7 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { buffer_length = length; buffer_index = 0; } + pa_stream_drop(s); } @@ -260,7 +264,7 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { const void *data; if (pa_stream_peek(s, &data, &length) < 0) { - pa_log(_("pa_stream_peek() failed: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } @@ -300,25 +304,25 @@ static void stream_state_callback(pa_stream *s, void *userdata) { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; - pa_log(_("Stream successfully created.\n")); + pa_log(_("Stream successfully created.")); if (!(a = pa_stream_get_buffer_attr(s))) - pa_log(_("pa_stream_get_buffer_attr() failed: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + pa_log(_("pa_stream_get_buffer_attr() failed: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); else { if (mode == PLAYBACK) - pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n"), a->maxlength, a->tlength, a->prebuf, a->minreq); + pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u"), a->maxlength, a->tlength, a->prebuf, a->minreq); else { pa_assert(mode == RECORD); - pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize); + pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u"), a->maxlength, a->fragsize); } } - pa_log(_("Using sample spec '%s', channel map '%s'.\n"), + pa_log(_("Using sample spec '%s', channel map '%s'."), pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); - pa_log(_("Connected to device %s (%u, %ssuspended).\n"), + pa_log(_("Connected to device %s (%u, %ssuspended)."), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); @@ -328,7 +332,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_FAILED: default: - pa_log(_("Stream error: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + pa_log(_("Stream error: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); quit(1); } } @@ -338,9 +342,9 @@ static void stream_suspended_callback(pa_stream *s, void *userdata) { if (verbose) { if (pa_stream_is_suspended(s)) - pa_log(_("Stream device suspended.%s \n"), CLEAR_LINE); + pa_log(_("Stream device suspended.%s"), CLEAR_LINE); else - pa_log(_("Stream device resumed.%s \n"), CLEAR_LINE); + pa_log(_("Stream device resumed.%s"), CLEAR_LINE); } } @@ -348,35 +352,35 @@ static void stream_underflow_callback(pa_stream *s, void *userdata) { pa_assert(s); if (verbose) - pa_log(_("Stream underrun.%s \n"), CLEAR_LINE); + pa_log(_("Stream underrun.%s"), CLEAR_LINE); } static void stream_overflow_callback(pa_stream *s, void *userdata) { pa_assert(s); if (verbose) - pa_log(_("Stream overrun.%s \n"), CLEAR_LINE); + pa_log(_("Stream overrun.%s"), CLEAR_LINE); } static void stream_started_callback(pa_stream *s, void *userdata) { pa_assert(s); if (verbose) - pa_log(_("Stream started.%s \n"), CLEAR_LINE); + pa_log(_("Stream started.%s"), CLEAR_LINE); } static void stream_moved_callback(pa_stream *s, void *userdata) { pa_assert(s); if (verbose) - pa_log(_("Stream moved to device %s (%u, %ssuspended).%s \n"), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : _("not "), CLEAR_LINE); + pa_log(_("Stream moved to device %s (%u, %ssuspended).%s"), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : _("not "), CLEAR_LINE); } static void stream_buffer_attr_callback(pa_stream *s, void *userdata) { pa_assert(s); if (verbose) - pa_log(_("Stream buffer attributes changed.%s \n"), CLEAR_LINE); + pa_log(_("Stream buffer attributes changed.%s"), CLEAR_LINE); } static void stream_event_callback(pa_stream *s, const char *name, pa_proplist *pl, void *userdata) { @@ -387,7 +391,7 @@ static void stream_event_callback(pa_stream *s, const char *name, pa_proplist *p pa_assert(pl); t = pa_proplist_to_string_sep(pl, ", "); - pa_log("Got event '%s', properties '%s'\n", name, t); + pa_log("Got event '%s', properties '%s'", name, t); pa_xfree(t); } @@ -409,10 +413,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_assert(!stream); if (verbose) - pa_log(_("Connection established.%s \n"), CLEAR_LINE); + pa_log(_("Connection established.%s"), CLEAR_LINE); if (!(stream = pa_stream_new_with_proplist(c, NULL, &sample_spec, &channel_map, proplist))) { - pa_log(_("pa_stream_new() failed: %s\n"), pa_strerror(pa_context_errno(c))); + pa_log(_("pa_stream_new() failed: %s"), pa_strerror(pa_context_errno(c))); goto fail; } @@ -440,13 +444,13 @@ static void context_state_callback(pa_context *c, void *userdata) { if (mode == PLAYBACK) { pa_cvolume cv; if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL)) < 0) { - pa_log(_("pa_stream_connect_playback() failed: %s\n"), pa_strerror(pa_context_errno(c))); + pa_log(_("pa_stream_connect_playback() failed: %s"), pa_strerror(pa_context_errno(c))); goto fail; } } else { if ((r = pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags)) < 0) { - pa_log(_("pa_stream_connect_record() failed: %s\n"), pa_strerror(pa_context_errno(c))); + pa_log(_("pa_stream_connect_record() failed: %s"), pa_strerror(pa_context_errno(c))); goto fail; } } @@ -460,7 +464,7 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_FAILED: default: - pa_log(_("Connection failure: %s\n"), pa_strerror(pa_context_errno(c))); + pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c))); goto fail; } @@ -493,12 +497,12 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { if (verbose) - pa_log(_("Got EOF.\n")); + pa_log(_("Got EOF.")); start_drain(); } else { - pa_log(_("read() failed: %s\n"), strerror(errno)); + pa_log(_("read() failed: %s"), strerror(errno)); quit(1); } @@ -530,7 +534,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve pa_assert(buffer_length); if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) { - pa_log(_("write() failed: %s\n"), strerror(errno)); + pa_log(_("write() failed: %s"), strerror(errno)); quit(1); mainloop_api->io_free(stdio_event); @@ -551,7 +555,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve /* UNIX signal to quit recieved */ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { if (verbose) - pa_log(_("Got signal, exiting.\n")); + pa_log(_("Got signal, exiting.")); quit(0); } @@ -565,7 +569,7 @@ static void stream_update_timing_callback(pa_stream *s, int success, void *userd if (!success || pa_stream_get_time(s, &usec) < 0 || pa_stream_get_latency(s, &l, &negative) < 0) { - pa_log(_("Failed to get latency: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("Failed to get latency: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } @@ -588,7 +592,7 @@ static void time_event_callback(pa_mainloop_api *m, pa_time_event *e, const stru if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) { pa_operation *o; if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) - pa_log(_("pa_stream_update_timing_info() failed: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("pa_stream_update_timing_info() failed: %s"), pa_strerror(pa_context_errno(context))); else pa_operation_unref(o); } @@ -753,7 +757,7 @@ int main(int argc, char *argv[]) { if (!(t = pa_locale_to_utf8(optarg)) || pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) { - pa_log(_("Invalid client name '%s'\n"), t ? t : optarg); + pa_log(_("Invalid client name '%s'"), t ? t : optarg); pa_xfree(t); goto quit; } @@ -769,7 +773,7 @@ int main(int argc, char *argv[]) { if (!(t = pa_locale_to_utf8(optarg)) || pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) { - pa_log(_("Invalid stream name '%s'\n"), t ? t : optarg); + pa_log(_("Invalid stream name '%s'"), t ? t : optarg); pa_xfree(t); goto quit; } @@ -806,7 +810,7 @@ int main(int argc, char *argv[]) { case ARG_CHANNELMAP: if (!pa_channel_map_parse(&channel_map, optarg)) { - pa_log(_("Invalid channel map '%s'\n"), optarg); + pa_log(_("Invalid channel map '%s'"), optarg); goto quit; } @@ -835,14 +839,14 @@ int main(int argc, char *argv[]) { case ARG_LATENCY: if (((latency = (size_t) atoi(optarg))) <= 0) { - pa_log(_("Invalid latency specification '%s'\n"), optarg); + pa_log(_("Invalid latency specification '%s'"), optarg); goto quit; } break; case ARG_PROCESS_TIME: if (((process_time = (size_t) atoi(optarg))) <= 0) { - pa_log(_("Invalid process time specification '%s'\n"), optarg); + pa_log(_("Invalid process time specification '%s'"), optarg); goto quit; } break; @@ -854,7 +858,7 @@ int main(int argc, char *argv[]) { pa_proplist_setp(proplist, t) < 0) { pa_xfree(t); - pa_log(_("Invalid property '%s'\n"), optarg); + pa_log(_("Invalid property '%s'"), optarg); goto quit; } @@ -890,7 +894,7 @@ int main(int argc, char *argv[]) { } if (!pa_sample_spec_valid(&sample_spec)) { - pa_log(_("Invalid sample specification\n")); + pa_log(_("Invalid sample specification")); goto quit; } @@ -900,19 +904,19 @@ int main(int argc, char *argv[]) { filename = argv[optind]; if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { - pa_log(_("open(): %s\n"), strerror(errno)); + pa_log(_("open(): %s"), strerror(errno)); goto quit; } if (dup2(fd, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO) < 0) { - pa_log(_("dup2(): %s\n"), strerror(errno)); + pa_log(_("dup2(): %s"), strerror(errno)); goto quit; } pa_close(fd); } else if (optind+1 <= argc) { - pa_log(_("Too many arguments.\n")); + pa_log(_("Too many arguments.")); goto quit; } @@ -923,7 +927,7 @@ int main(int argc, char *argv[]) { if (mode == RECORD) { /* This might patch up the sample spec */ if (pa_sndfile_write_sample_spec(&sfi, &sample_spec) < 0) { - pa_log(_("Failed to generate sample specification for file.\n")); + pa_log(_("Failed to generate sample specification for file.")); goto quit; } @@ -943,16 +947,16 @@ int main(int argc, char *argv[]) { if (!(sndfile = sf_open_fd(mode == RECORD ? STDOUT_FILENO : STDIN_FILENO, mode == RECORD ? SFM_WRITE : SFM_READ, &sfi, 0))) { - pa_log(_("Failed to open audio file.\n")); + pa_log(_("Failed to open audio file.")); goto quit; } if (mode == PLAYBACK) { if (sample_spec_set) - pa_log(_("Warning: specified sample specification will be overwritten with specification from file.\n")); + pa_log(_("Warning: specified sample specification will be overwritten with specification from file.")); if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) { - pa_log(_("Failed to determine sample specification from file.\n")); + pa_log(_("Failed to determine sample specification from file.")); goto quit; } sample_spec_set = TRUE; @@ -961,7 +965,7 @@ int main(int argc, char *argv[]) { /* Allow the user to overwrite the channel map on the command line */ if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) { if (sample_spec.channels > 2) - pa_log(_("Warning: Failed to determine channel map from file.\n")); + pa_log(_("Warning: Failed to determine channel map from file.")); } else channel_map_set = TRUE; } @@ -972,7 +976,7 @@ int main(int argc, char *argv[]) { pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); if (!pa_channel_map_compatible(&channel_map, &sample_spec)) { - pa_log(_("Channel map doesn't match sample specification\n")); + pa_log(_("Channel map doesn't match sample specification")); goto quit; } @@ -983,7 +987,7 @@ int main(int argc, char *argv[]) { readf_function = pa_sndfile_readf_function(&sample_spec); else { if (pa_sndfile_write_channel_map(sndfile, &channel_map) < 0) - pa_log(_("Warning: failed to write channel map to file.\n")); + pa_log(_("Warning: failed to write channel map to file.")); writef_function = pa_sndfile_writef_function(&sample_spec); } @@ -998,7 +1002,7 @@ int main(int argc, char *argv[]) { if (verbose) { char tss[PA_SAMPLE_SPEC_SNPRINT_MAX], tcm[PA_CHANNEL_MAP_SNPRINT_MAX]; - pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'.\n"), + pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'."), mode == RECORD ? _("recording") : _("playback"), pa_sample_spec_snprint(tss, sizeof(tss), &sample_spec), pa_channel_map_snprint(tcm, sizeof(tcm), &channel_map)); @@ -1025,7 +1029,7 @@ int main(int argc, char *argv[]) { /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { - pa_log(_("pa_mainloop_new() failed.\n")); + pa_log(_("pa_mainloop_new() failed.")); goto quit; } @@ -1044,14 +1048,14 @@ int main(int argc, char *argv[]) { mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { - pa_log(_("io_new() failed.\n")); + pa_log(_("io_new() failed.")); goto quit; } } /* Create a new connection context */ if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) { - pa_log(_("pa_context_new() failed.\n")); + pa_log(_("pa_context_new() failed.")); goto quit; } @@ -1059,20 +1063,20 @@ int main(int argc, char *argv[]) { /* Connect the context */ if (pa_context_connect(context, server, 0, NULL) < 0) { - pa_log(_("pa_context_connect() failed: %s\n"), pa_strerror(pa_context_errno(context))); + pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); goto quit; } if (verbose) { if (!(time_event = pa_context_rttime_new(context, pa_rtclock_now() + TIME_EVENT_USEC, time_event_callback, NULL))) { - pa_log(_("pa_context_rttime_new() failed.\n")); + pa_log(_("pa_context_rttime_new() failed.")); goto quit; } } /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { - pa_log(_("pa_mainloop_run() failed.\n")); + pa_log(_("pa_mainloop_run() failed.")); goto quit; } -- cgit From 18433c19b690432179e9a0ed83eff611f5cecc67 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 13:45:59 +0200 Subject: alsa: handle correctly if alsa returns us 0 or EAGAIN on snd_pcm_mmap_begin if we didn't call snd_pcm_avail immediately before --- src/modules/alsa/alsa-sink.c | 22 ++++++++++++++++++---- src/modules/alsa/alsa-source.c | 28 +++++++++++++++++++++------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index e7925902..46562cbd 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -401,6 +401,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle snd_pcm_sframes_t n; size_t n_bytes; int r; + pa_bool_t after_avail = TRUE; /* First we determine how many samples are missing to fill the * buffer up to 100% */ @@ -484,6 +485,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle if (PA_UNLIKELY((err = pa_alsa_safe_mmap_begin(u->pcm_handle, &areas, &offset, &frames, u->hwbuf_size, &u->sink->sample_spec)) < 0)) { + if (!after_avail && err == -EAGAIN) + break; + if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0) continue; @@ -494,9 +498,12 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size) frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size; - if (frames == 0) + if (!after_avail && frames == 0) break; + pa_assert(frames > 0); + after_avail = FALSE; + /* Check these are multiples of 8 bit */ pa_assert((areas[0].first & 7) == 0); pa_assert((areas[0].step & 7)== 0); @@ -617,6 +624,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle for (;;) { snd_pcm_sframes_t frames; void *p; + pa_bool_t after_avail = TRUE; /* pa_log_debug("%lu frames to write", (unsigned long) frames); */ @@ -634,17 +642,23 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, (snd_pcm_uframes_t) frames); pa_memblock_release(u->memchunk.memblock); - if (frames == 0) - break; - if (PA_UNLIKELY(frames < 0)) { + if (!after_avail && (int) frames == -EAGAIN) + break; + if ((r = try_recover(u, "snd_pcm_writei", (int) frames)) == 0) continue; return r; } + if (!after_avail && frames == 0) + break; + + pa_assert(frames > 0); + after_avail = FALSE; + u->memchunk.index += (size_t) frames * u->frame_size; u->memchunk.length -= (size_t) frames * u->frame_size; diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 41bb768b..8a1fbe5f 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -391,6 +391,7 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled snd_pcm_sframes_t n; size_t n_bytes; int r; + pa_bool_t after_avail = TRUE; if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) { @@ -463,6 +464,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled if (PA_UNLIKELY((err = pa_alsa_safe_mmap_begin(u->pcm_handle, &areas, &offset, &frames, u->hwbuf_size, &u->source->sample_spec)) < 0)) { + if (!after_avail && err == -EAGAIN) + break; + if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0) continue; @@ -473,9 +477,12 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size) frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size; - if (frames == 0) + if (!after_avail && frames == 0) break; + pa_assert(frames > 0); + after_avail = FALSE; + /* Check these are multiples of 8 bit */ pa_assert((areas[0].first & 7) == 0); pa_assert((areas[0].step & 7)== 0); @@ -542,6 +549,7 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled snd_pcm_sframes_t n; size_t n_bytes; int r; + pa_bool_t after_avail = TRUE; if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) { @@ -602,20 +610,26 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, (snd_pcm_uframes_t) frames); pa_memblock_release(chunk.memblock); - if (frames == 0) { - pa_memblock_unref(chunk.memblock); - break; - } - if (PA_UNLIKELY(frames < 0)) { pa_memblock_unref(chunk.memblock); - if ((r = try_recover(u, "snd_pcm_readi", (int) (frames))) == 0) + if (!after_avail && (int) frames == -EAGAIN) + break; + + if ((r = try_recover(u, "snd_pcm_readi", (int) frames)) == 0) continue; return r; } + if (!after_avail && frames == 0) { + pa_memblock_unref(chunk.memblock); + break; + } + + pa_assert(frames > 0); + after_avail = FALSE; + chunk.index = 0; chunk.length = (size_t) frames * u->frame_size; -- cgit From 2bbdf631f8ef1029558be19bcf8a9176a5932b8b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 13:58:22 +0200 Subject: udev: explain what happened when inotify_add_watch() returned ENOSPC, rhbz #513571 --- src/modules/module-udev-detect.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c index c8ec2bf9..11de1ccb 100644 --- a/src/modules/module-udev-detect.c +++ b/src/modules/module-udev-detect.c @@ -336,8 +336,18 @@ static int setup_inotify(struct userdata *u) { pa_close(u->inotify_fd); u->inotify_fd = -1; - if (saved_errno == ENOENT) + if (saved_errno == ENOENT) { + pa_log_debug("/dev/snd/ is apparently not existing yet, retrying to create inotify watch later."); return 0; + } + + if (saved_errno == ENOSPC) { + pa_log("You apparently ran out of inotify watches, probably because Tracker/Beagle took them all away. " + "I wished people would do their homework first and fix inotify before using it for watching whole " + "directory trees which is something the current inotify is certainly not useful for. " + "Please make sure to drop the Tracker/Beagle guys a line complaining about their broken use of inotify."); + return 0; + } pa_log("inotify_add_watch() failed: %s", pa_cstrerror(saved_errno)); return -1; -- cgit From 5e24b6dff532ef82e028a78f020a826032493b2e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 15:49:22 +0200 Subject: memblock: try to hit an assert earlier when ref counting doesn't work --- src/pulsecore/memblock.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 2c3f98a5..3bc10de5 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -96,6 +96,7 @@ struct pa_memimport_segment { unsigned n_blocks; }; +/* A collection of multiple segments */ struct pa_memimport { pa_mutex *mutex; @@ -514,9 +515,9 @@ static void memblock_free(pa_memblock *b) { pa_mutex_lock(import->mutex); - pa_hashmap_remove( - import->blocks, - PA_UINT32_TO_PTR(b->per_type.imported.id)); + pa_assert_se(pa_hashmap_remove( + import->blocks, + PA_UINT32_TO_PTR(b->per_type.imported.id))); pa_assert(segment->n_blocks >= 1); if (-- segment->n_blocks <= 0) @@ -677,9 +678,9 @@ static void memblock_replace_import(pa_memblock *b) { pa_mutex_lock(import->mutex); - pa_hashmap_remove( - import->blocks, - PA_UINT32_TO_PTR(b->per_type.imported.id)); + pa_assert_se(pa_hashmap_remove( + import->blocks, + PA_UINT32_TO_PTR(b->per_type.imported.id))); memblock_make_local(b); @@ -960,6 +961,11 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i pa_mutex_lock(i->mutex); + if ((b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(block_id)))) { + pa_memblock_ref(b); + goto finish; + } + if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) goto finish; @@ -989,12 +995,11 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i seg->n_blocks++; + stat_add(b); + finish: pa_mutex_unlock(i->mutex); - if (b) - stat_add(b); - return b; } -- cgit From f6763917ee757845e2c52e36975d948bc93d8b6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 18:22:13 +0200 Subject: autospawn: refuse autospawning if process disabled waitpid() --- src/pulse/context.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 4ded5565..ab1c1638 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -668,11 +668,24 @@ static pa_strlist *prepend_per_user(pa_strlist *l) { static int context_autospawn(pa_context *c) { pid_t pid; int status, r; - - pa_log_debug("Trying to autospawn..."); + struct sigaction sa; pa_context_ref(c); + if (sigaction(SIGCHLD, NULL, &sa) < 0) { + pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno)); + pa_context_fail(c, PA_ERR_INTERNAL); + goto fail; + } + + if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) { + pa_log_debug("Process disabled waitpid(), cannot autospawn."); + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); + goto fail; + } + + pa_log_debug("Trying to autospawn..."); + if (c->spawn_api.prefork) c->spawn_api.prefork(); -- cgit From 5efb07281d5be1cddaed5b0610325fedd7f599ec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 20:13:52 +0200 Subject: alsa: throw timing data away after device resume --- src/modules/alsa/alsa-sink.c | 6 +++++- src/modules/alsa/alsa-source.c | 4 +++- src/pulse/stream.c | 2 +- src/pulsecore/time-smoother.c | 41 ++++++++++++++++++++--------------------- src/pulsecore/time-smoother.h | 2 +- 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 46562cbd..7fc602be 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -899,9 +899,13 @@ static int unsuspend(struct userdata *u) { if (build_pollfd(u) < 0) goto fail; + u->write_count = 0; + pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE); + u->first = TRUE; u->since_start = 0; + pa_log_info("Resumed successfully..."); return 0; @@ -1204,7 +1208,7 @@ static int process_rewind(struct userdata *u) { if (rewind_nbytes <= 0) pa_log_info("Tried rewind, but was apparently not possible."); else { - u->write_count -= out_frames * u->frame_size; + u->write_count -= rewind_nbytes; pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes); pa_sink_process_rewind(u->sink, rewind_nbytes); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 8a1fbe5f..ed9c1480 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -854,7 +854,9 @@ static int unsuspend(struct userdata *u) { /* FIXME: We need to reload the volume somehow */ snd_pcm_start(u->pcm_handle); - pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE); + + u->read_count = 0; + pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE); pa_log_info("Resumed successfully..."); diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 5baf5c2c..a22816ae 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -827,7 +827,7 @@ static void create_stream_complete(pa_stream *s) { if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC; pa_assert(!s->auto_timing_update_event); - s->auto_timing_update_event = pa_context_rttime_new(s->context, pa_rtclock_now() + s->auto_timing_interval_usec, &auto_timing_update_callback, s); + s->auto_timing_update_event = pa_context_rttime_new(s->context, pa_rtclock_now() + s->auto_timing_interval_usec, &auto_timing_update_callback, s); request_auto_timing_update(s, TRUE); } diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c index 9d5a0705..1289f2b6 100644 --- a/src/pulsecore/time-smoother.c +++ b/src/pulsecore/time-smoother.c @@ -108,29 +108,11 @@ pa_smoother* pa_smoother_new( s = pa_xnew(pa_smoother, 1); s->adjust_time = adjust_time; s->history_time = history_time; - s->time_offset = 0; + s->min_history = min_history; s->monotonic = monotonic; - - s->px = s->py = 0; - s->dp = 1; - - s->ex = s->ey = s->ry = 0; - s->de = 1; - - s->history_idx = 0; - s->n_history = 0; - - s->last_y = s->last_x = 0; - - s->abc_valid = FALSE; - - s->paused = FALSE; s->smoothing = smoothing; - s->min_history = min_history; - - s->paused = paused; - s->time_offset = s->pause_time = time_offset; + pa_smoother_reset(s, time_offset, paused); return s; } @@ -514,9 +496,26 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay) return (pa_usec_t) llrint((double) y_delay / nde); } -void pa_smoother_reset(pa_smoother *s) { +void pa_smoother_reset(pa_smoother *s, pa_usec_t time_offset, pa_bool_t paused) { pa_assert(s); + s->px = s->py = 0; + s->dp = 1; + + s->ex = s->ey = s->ry = 0; + s->de = 1; + + s->history_idx = 0; s->n_history = 0; + + s->last_y = s->last_x = 0; + s->abc_valid = FALSE; + + s->paused = paused; + s->time_offset = s->pause_time = time_offset; + + /* #ifdef DEBUG_DATA */ + pa_log_debug("reset()"); +/* #endif */ } diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h index 5244a7e7..63d33e48 100644 --- a/src/pulsecore/time-smoother.h +++ b/src/pulsecore/time-smoother.h @@ -52,7 +52,7 @@ void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t x_offset); void pa_smoother_pause(pa_smoother *s, pa_usec_t x); void pa_smoother_resume(pa_smoother *s, pa_usec_t x, pa_bool_t abrupt); -void pa_smoother_reset(pa_smoother *s); +void pa_smoother_reset(pa_smoother *s, pa_usec_t time_offset, pa_bool_t paused); void pa_smoother_fix_now(pa_smoother *s); -- cgit From e7ca058427e795b9c2b436c4a819e8d8354ee9de Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 20:20:34 +0200 Subject: client: make volume struct const --- src/pulse/stream.c | 2 +- src/pulse/stream.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulse/stream.c b/src/pulse/stream.c index a22816ae..bbd01499 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -1172,7 +1172,7 @@ int pa_stream_connect_playback( const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, - pa_cvolume *volume, + const pa_cvolume *volume, pa_stream *sync_stream) { pa_assert(s); diff --git a/src/pulse/stream.h b/src/pulse/stream.h index fecc5870..eeffc0c9 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -405,7 +405,7 @@ int pa_stream_connect_playback( const char *dev /**< Name of the sink to connect to, or NULL for default */ , const pa_buffer_attr *attr /**< Buffering attributes, or NULL for default */, pa_stream_flags_t flags /**< Additional flags, or 0 for default */, - pa_cvolume *volume /**< Initial volume, or NULL for default */, + const pa_cvolume *volume /**< Initial volume, or NULL for default */, pa_stream *sync_stream /**< Synchronize this stream with the specified one, or NULL for a standalone stream*/); /** Connect the stream to a source */ -- cgit From 211d0f3dcb23c6d63dd6a212826a872ce972e4ee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 20:21:30 +0200 Subject: client: limit block size for zero-copy operations to mempool block size --- src/pulse/stream.c | 11 +++++++++++ src/pulse/stream.h | 13 +++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/pulse/stream.c b/src/pulse/stream.c index bbd01499..72d49e11 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -1207,6 +1207,17 @@ int pa_stream_begin_write( PA_CHECK_VALIDITY(s->context, data, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, nbytes && *nbytes != 0, PA_ERR_INVALID); + if (*nbytes != (size_t) -1) { + size_t m, fs; + + m = pa_mempool_block_size_max(s->context->mempool); + fs = pa_frame_size(&s->sample_spec); + + m = (m / fs) * fs; + if (*nbytes > m) + *nbytes = m; + } + if (!s->write_memblock) { s->write_memblock = pa_memblock_new(s->context->mempool, *nbytes); s->write_data = pa_memblock_acquire(s->write_memblock); diff --git a/src/pulse/stream.h b/src/pulse/stream.h index eeffc0c9..cb8b74dc 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -425,7 +425,7 @@ int pa_stream_disconnect(pa_stream *s); * to a pointer and an address of the number of bytes you want to * write. On return the two values will contain a pointer where you * can place the data to write and the maximum number of bytes you can - * write. On return *nbytes can be larger or have the same value as + * write. On return *nbytes can be smaller or have the same value as * you passed in. You need to be able to handle both cases. Accessing * memory beyond the returned *nbytes value is invalid. Acessing the * memory returned after the following pa_stream_write() or @@ -442,7 +442,7 @@ int pa_stream_disconnect(pa_stream *s); * amount of time pass after calling pa_stream_begin_write() and * before calling pa_stream_write(). If you want to cancel a * previously called pa_stream_begin_write() without calling - * pa_stream_write() use pa_stream_cancel_write() instead. Calling + * pa_stream_write() use pa_stream_cancel_write(). Calling * pa_stream_begin_write() twice without calling pa_stream_write() or * pa_stream_cancel_write() in between will return exactly the same * pointer/nbytes values.\since 0.9.16 */ @@ -492,10 +492,11 @@ int pa_stream_write( pa_seek_mode_t seek /**< Seek mode, must be PA_SEEK_RELATIVE for upload streams */); /** Read the next fragment from the buffer (for recording streams). - * data will point to the actual data and length will contain the size - * of the data in bytes (which can be less than a complete framgnet). - * Use pa_stream_drop() to actually remove the data from the - * buffer. If no data is available will return a NULL pointer */ + * data will point to the actual data and nbytes will contain the size + * of the data in bytes (which can be less or more than a complete + * fragment). Use pa_stream_drop() to actually remove the data from + * the buffer. If no data is available this will return a NULL + * pointer */ int pa_stream_peek( pa_stream *p /**< The stream to use */, const void **data /**< Pointer to pointer that will point to data */, -- cgit From 59659e1db64d2a88787943da75cf6c510d0ad98f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jul 2009 20:22:19 +0200 Subject: interpol-test: allow configuration of latency --- src/tests/interpol-test.c | 81 +++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 0c906d3e..007555c3 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -43,20 +43,37 @@ 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 nbytes, void *userdata) { /* Just some silence */ - pa_assert_se(pa_stream_write(p, pa_xmalloc0(nbytes), nbytes, pa_xfree, 0, PA_SEEK_RELATIVE) == 0); + + 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, just drop the data */ + /* We don't care about the data, just drop it */ - while (pa_stream_readable_size(p) > 0) { - const void *d; - size_t b; + for (;;) { + const void *data; - pa_assert_se(pa_stream_peek(p, &d, &b) == 0); + 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); } } @@ -82,27 +99,36 @@ static void context_state_callback(pa_context *c, void *userdata) { 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 = 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_assert_se(stream = pa_stream_new(c, "interpol-test", &ss, NULL)); if (playback) { - pa_assert_se(pa_stream_connect_playback(stream, NULL, NULL, flags, NULL, NULL) == 0); + 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, NULL, flags) == 0); + pa_assert_se(pa_stream_connect_record(stream, NULL, &attr, flags) == 0); pa_stream_set_read_callback(stream, stream_read_cb, NULL); } @@ -123,7 +149,7 @@ 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 @@ -134,24 +160,22 @@ int main(int argc, char *argv[]) { playback = argc <= 1 || !pa_streq(argv[1], "-r"); - /* Set up a new main loop */ - m = pa_threaded_mainloop_new(); - assert(m); - - mainloop_api = pa_threaded_mainloop_get_api(m); + latency = + (argc >= 2 && !pa_streq(argv[1], "-r")) ? atoi(argv[1]) : + (argc >= 3 ? atoi(argv[2]) : 0); - context = pa_context_new(mainloop_api, argv[0]); - assert(context); + /* 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); - r = pa_threaded_mainloop_start(m); - assert(r >= 0); + pa_assert_se(pa_threaded_mainloop_start(m) >= 0); /* #ifdef CORK */ for (k = 0; k < 20000; k++) @@ -160,7 +184,7 @@ int main(int argc, char *argv[]) { /* #endif */ { pa_bool_t success = FALSE, changed = FALSE; - pa_usec_t t, rtc; + pa_usec_t t, rtc, d; struct timeval now, tv; pa_bool_t playing = FALSE; @@ -169,7 +193,8 @@ int main(int argc, char *argv[]) { if (stream) { const pa_timing_info *info; - if (pa_stream_get_time(stream, &t) >= 0) + 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))) { @@ -191,14 +216,16 @@ int main(int argc, char *argv[]) { pa_bool_t cork_now; #endif rtc = pa_timeval_diff(&now, &start); - printf("%i\t%llu\t%llu\t%llu\t%llu\t%lli\t%u\t%u\n", k, + 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); + playing, + (unsigned long long) latency, + (unsigned long long) d); fflush(stdout); old_t = t; -- cgit From 6ce7d208f066f02ee837686e81faa1463a5e2945 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 25 Jul 2009 01:29:36 +0200 Subject: client: if a child we created was already reaped, assume that it was successful --- src/pulse/context.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index ab1c1638..7ba33249 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -743,9 +743,16 @@ static int context_autospawn(pa_context *c) { } while (r < 0 && errno == EINTR); if (r < 0) { - pa_log(_("waitpid(): %s"), pa_cstrerror(errno)); - pa_context_fail(c, PA_ERR_INTERNAL); - goto fail; + + if (errno != ESRCH) { + pa_log(_("waitpid(): %s"), pa_cstrerror(errno)); + pa_context_fail(c, PA_ERR_INTERNAL); + goto fail; + } + + /* hmm, something already reaped our child, so we assume + * startup worked, even if we cannot know */ + } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto fail; -- cgit From 8343360da1d8d93e8e3818ab91e7f764a1c8c99e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 25 Jul 2009 03:11:09 +0200 Subject: client: minor modernizations --- src/pulse/context.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 7ba33249..7c3717fa 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -701,9 +701,8 @@ static int context_autospawn(pa_context *c) { /* Child */ const char *state = NULL; -#define MAX_ARGS 64 - const char * argv[MAX_ARGS+1]; - int n; + const char * argv[32]; + unsigned n = 0; if (c->spawn_api.atfork) c->spawn_api.atfork(); @@ -712,12 +711,10 @@ static int context_autospawn(pa_context *c) { /* Setup argv */ - n = 0; - argv[n++] = c->conf->daemon_binary; argv[n++] = "--start"; - while (n < MAX_ARGS) { + while (n < PA_ELEMENTSOF(argv)-1) { char *a; if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) @@ -727,10 +724,10 @@ static int context_autospawn(pa_context *c) { } argv[n++] = NULL; + pa_assert(n <= PA_ELEMENTSOF(argv)); execv(argv[0], (char * const *) argv); _exit(1); -#undef MAX_ARGS } /* Parent */ -- cgit