diff options
Diffstat (limited to 'src/pulsecore')
27 files changed, 305 insertions, 70 deletions
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c index 5c7af2a8..e191b05f 100644 --- a/src/pulsecore/asyncmsgq.c +++ b/src/pulsecore/asyncmsgq.c @@ -159,7 +159,7 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi pa_assert_se(i.semaphore); - /* Thus mutex makes the queue multiple-writer safe. This lock is only used on the writing side */ + /* This mutex makes the queue multiple-writer safe. This lock is only used on the writing side */ pa_mutex_lock(a->mutex); pa_assert_se(pa_asyncq_push(a->asyncq, &i, TRUE) == 0); pa_mutex_unlock(a->mutex); @@ -196,7 +196,13 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u if (chunk) *chunk = a->current->memchunk; -/* pa_log_debug("Get q=%p object=%p (%s) code=%i data=%p chunk.length=%lu", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, (unsigned long) a->current->memchunk.length); */ +/* pa_log_debug("Get q=%p object=%p (%s) code=%i data=%p chunk.length=%lu", */ +/* (void*) a, */ +/* (void*) a->current->object, */ +/* a->current->object ? a->current->object->parent.type_name : NULL, */ +/* a->current->code, */ +/* (void*) a->current->userdata, */ +/* (unsigned long) a->current->memchunk.length); */ return 0; } diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 8e1ba536..515d1f90 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -229,7 +229,7 @@ int pa_card_set_profile(pa_card *c, const char *name) { pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); - pa_log_info("Successfully changed profile of card %u \"%s\" to %s", c->index, c->name, profile->name); + pa_log_info("Changed profile of card %u \"%s\" to %s", c->index, c->name, profile->name); c->active_profile = profile; diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 1df0bd63..5e45c1aa 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -401,7 +401,6 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b } static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { - pa_module *m; const char *name; pa_core_assert_ref(c); @@ -414,7 +413,7 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b return -1; } - if (!(m = pa_module_load(c, name, pa_tokenizer_get(t, 2)))) { + if (!pa_module_load(c, name, pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "Module load failed.\n"); return -1; } diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c index 3d6c2c3b..d9caa946 100644 --- a/src/pulsecore/core-error.c +++ b/src/pulsecore/core-error.c @@ -47,6 +47,9 @@ const char* pa_cstrerror(int errnum) { char *translated, *t; char errbuf[128]; + if (errnum < 0) + errnum = -errnum; + if ((t = PA_STATIC_TLS_GET(cstrerror))) pa_xfree(t); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index ad6c6ca9..a184bebd 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -704,7 +704,7 @@ void pa_reset_priority(void) { #endif } -static int match(const char *expr, const char *v) { +int pa_match(const char *expr, const char *v) { int k; regex_t re; int r; @@ -744,12 +744,12 @@ int pa_parse_boolean(const char *v) { /* And then we check language dependant */ if ((expr = nl_langinfo(YESEXPR))) if (expr[0]) - if ((r = match(expr, v)) > 0) + if ((r = pa_match(expr, v)) > 0) return 1; if ((expr = nl_langinfo(NOEXPR))) if (expr[0]) - if ((r = match(expr, v)) > 0) + if ((r = pa_match(expr, v)) > 0) return 0; errno = EINVAL; @@ -1411,6 +1411,7 @@ static int make_random_dir_and_link(mode_t m, const char *k) { return -1; } + pa_xfree(p); return 0; } @@ -1443,6 +1444,7 @@ char *pa_get_runtime_dir(void) { if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) { pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno)); + pa_xfree(d); goto fail; } @@ -2459,7 +2461,7 @@ char *pa_machine_id(void) { pa_strip_nl(ln); - if (ln[0]) + if (r && ln[0]) return pa_xstrdup(ln); } @@ -2604,3 +2606,28 @@ char *pa_unescape(char *p) { return p; } + +char *pa_realpath(const char *path) { + char *r, *t; + pa_assert(path); + + /* We want only abolsute paths */ + if (path[0] != '/') { + errno = EINVAL; + return NULL; + } + +#ifndef __GLIBC__ +#error "It's not clear whether this system supports realpath(..., NULL) like GNU libc does. If it doesn't we need a private version of realpath() here." +#endif + + if (!(r = realpath(path, NULL))) + return NULL; + + /* We copy this here in case our pa_xmalloc() is not implemented + * on top of libc malloc() */ + t = pa_xstrdup(r); + pa_xfree(r); + + return t; +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 442815f1..0ba33f31 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -141,6 +141,8 @@ size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap); char *pa_truncate_utf8(char *c, size_t l); +int pa_match(const char *expr, const char *v); + char *pa_getcwd(void); char *pa_make_path_absolute(const char *p); pa_bool_t pa_is_path_absolute(const char *p); @@ -219,4 +221,6 @@ char *pa_replace(const char*s, const char*a, const char *b); char *pa_unescape(char *p); +char *pa_realpath(const char *path); + #endif diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index 3c6f41ec..57607b69 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -138,7 +138,7 @@ int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { hash = h->hash_func(key) % NBUCKETS; - if ((e = hash_scan(h, hash, key))) + if (hash_scan(h, hash, key)) return -1; if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries)))) diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c index 87551232..012a1a05 100644 --- a/src/pulsecore/inet_ntop.c +++ b/src/pulsecore/inet_ntop.c @@ -38,7 +38,9 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { struct in_addr *in = (struct in_addr*)src; +#ifdef HAVE_IPV6 struct in6_addr *in6 = (struct in6_addr*)src; +#endif assert(src && dst); @@ -57,6 +59,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { (int)(in->s_addr >> 24) & 0xff); #endif break; +#ifdef HAVE_IPV6 case AF_INET6: pa_snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x", in6->s6_addr[ 0] << 8 | in6->s6_addr[ 1], @@ -68,6 +71,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { in6->s6_addr[12] << 8 | in6->s6_addr[13], in6->s6_addr[14] << 8 | in6->s6_addr[15]); break; +#endif default: errno = EAFNOSUPPORT; return NULL; diff --git a/src/pulsecore/inet_pton.c b/src/pulsecore/inet_pton.c index d191e550..abdfa467 100644 --- a/src/pulsecore/inet_pton.c +++ b/src/pulsecore/inet_pton.c @@ -38,7 +38,9 @@ int inet_pton(int af, const char *src, void *dst) { struct in_addr *in = (struct in_addr*)dst; +#ifdef HAVE_IPV6 struct in6_addr *in6 = (struct in6_addr*)dst; +#endif assert(src && dst); @@ -48,8 +50,10 @@ int inet_pton(int af, const char *src, void *dst) { if (in->s_addr == INADDR_NONE) return 0; break; +#ifdef HAVE_IPV6 case AF_INET6: /* FIXME */ +#endif default: errno = EAFNOSUPPORT; return -1; diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 6d5080fb..312e0403 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -62,7 +62,9 @@ struct acl_entry { PA_LLIST_FIELDS(struct acl_entry); int family; struct in_addr address_ipv4; +#ifdef HAVE_IPV6 struct in6_addr address_ipv6; +#endif int bits; }; @@ -109,6 +111,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0) pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits); +#ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) { e.bits = bits == (uint32_t) -1 ? 128 : (int) bits; @@ -138,6 +141,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (t) pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } +#endif } else { pa_log_warn("Failed to parse address: %s", a); @@ -183,14 +187,20 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (getpeername(fd, (struct sockaddr*) &sa, &salen) < 0) return -1; +#ifdef HAVE_IPV6 if (sa.ss_family != AF_INET && sa.ss_family != AF_INET6) +#else + if (sa.ss_family != AF_INET) +#endif return -1; if (sa.ss_family == AF_INET && salen != sizeof(struct sockaddr_in)) return -1; +#ifdef HAVE_IPV6 if (sa.ss_family == AF_INET6 && salen != sizeof(struct sockaddr_in6)) return -1; +#endif for (e = acl->entries; e; e = e->next) { @@ -203,6 +213,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (e->bits == 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */ (ntohl(sai->sin_addr.s_addr ^ e->address_ipv4.s_addr) >> (32 - e->bits)) == 0) return 1; +#ifdef HAVE_IPV6 } else if (e->family == AF_INET6) { int i, bits ; struct sockaddr_in6 *sai = (struct sockaddr_in6*) &sa; @@ -230,6 +241,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (bits == 0) return 1; } +#endif } } diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 1ae43839..89b75da3 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -351,6 +351,7 @@ void pa_log_levelv_meta( } errno = saved_errno; + pa_xfree(bt); } void pa_log_level_meta( diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 1d7f4559..fbf0a470 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -57,7 +57,7 @@ #define PA_MEMEXPORT_SLOTS_MAX 128 -#define PA_MEMIMPORT_SLOTS_MAX 128 +#define PA_MEMIMPORT_SLOTS_MAX 160 #define PA_MEMIMPORT_SEGMENTS_MAX 16 struct pa_memblock { diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c index 8a447cf7..bdae0e65 100644 --- a/src/pulsecore/proplist-util.c +++ b/src/pulsecore/proplist-util.c @@ -34,6 +34,7 @@ extern char **environ; #endif +#include <pulse/gccmacro.h> #include <pulse/proplist.h> #include <pulse/utf8.h> #include <pulse/xmalloc.h> @@ -41,8 +42,64 @@ extern char **environ; #include <pulsecore/core-util.h> +#if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF) +#include <glib.h> +static G_CONST_RETURN gchar* _g_get_application_name(void) PA_GCC_WEAKREF(g_get_application_name); +#endif + +#if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF) +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +static G_CONST_RETURN gchar* _gtk_window_get_default_icon_name(void) PA_GCC_WEAKREF(gtk_window_get_default_icon_name); +static Display *_gdk_display PA_GCC_WEAKREF(gdk_display); +#endif + #include "proplist-util.h" +static void add_glib_properties(pa_proplist *p) { + +#if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF) + + if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) + if (_g_get_application_name) { + const gchar *t; + + /* We ignore the tiny race condition here. */ + + if ((t = _g_get_application_name())) + pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t); + } + +#endif +} + +static void add_gtk_properties(pa_proplist *p) { + +#if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF) + + if (!pa_proplist_contains(p, PA_PROP_APPLICATION_ICON_NAME)) + if (_gtk_window_get_default_icon_name) { + const gchar *t; + + /* We ignore the tiny race condition here. */ + + if ((t = _gtk_window_get_default_icon_name())) + pa_proplist_sets(p, PA_PROP_APPLICATION_ICON_NAME, t); + } + + if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY)) + if (&_gdk_display && _gdk_display) { + const char *t; + + /* We ignore the tiny race condition here. */ + + if ((t = DisplayString(_gdk_display))) + pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, t); + } + +#endif +} + void pa_init_proplist(pa_proplist *p) { char **e; const char *pp; @@ -58,18 +115,27 @@ void pa_init_proplist(pa_proplist *p) { for (e = environ; *e; e++) { if (pa_startswith(*e, "PULSE_PROP_")) { - size_t kl = strcspn(*e+11, "="); + size_t kl, skip; char *k; + pa_bool_t override; - if ((*e)[11+kl] != '=') - continue; + if (pa_startswith(*e, "PULSE_PROP_OVERRIDE_")) { + skip = 20; + override = TRUE; + } else { + skip = 11; + override = FALSE; + } - if (!pa_utf8_valid(*e+11+kl+1)) + kl = strcspn(*e+skip, "="); + + if ((*e)[skip+kl] != '=') continue; - k = pa_xstrndup(*e+11, kl); + k = pa_xstrndup(*e+skip, kl); - pa_proplist_sets(p, k, *e+11+kl+1); + if (override || !pa_proplist_contains(p, k)) + pa_proplist_sets(p, k, *e+skip+kl+1); pa_xfree(k); } } @@ -79,6 +145,15 @@ void pa_init_proplist(pa_proplist *p) { pa_proplist *t; if ((t = pa_proplist_from_string(pp))) { + pa_proplist_update(p, PA_UPDATE_MERGE, t); + pa_proplist_free(t); + } + } + + if ((pp = getenv("PULSE_PROP_OVERRIDE"))) { + pa_proplist *t; + + if ((t = pa_proplist_from_string(pp))) { pa_proplist_update(p, PA_UPDATE_REPLACE, t); pa_proplist_free(t); } @@ -117,20 +192,8 @@ void pa_init_proplist(pa_proplist *p) { } } -#ifdef RTLD_NOLOAD - if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) { - void *dl; - - if ((dl = dlopen("libglib-2.0", RTLD_NOLOAD))) { - const char *(*_g_get_application_name)(void); - - if ((*(void**) &_g_get_application_name = dlsym(dl, "g_get_application_name"))) - pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, _g_get_application_name()); - - dlclose(dl); - } - } -#endif + add_glib_properties(p); + add_gtk_properties(p); if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) { const char *t; diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index e1643cbb..840f4581 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -924,7 +924,7 @@ static int do_read(connection *c) { c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request); - if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { + if (c->request < ESD_PROTO_CONNECT || c->request >= ESD_PROTO_MAX) { pa_log("recieved invalid request."); return -1; } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index c3032618..a963f78a 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2560,7 +2560,10 @@ static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uin if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID))) name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME); - CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); + if (!name || !pa_namereg_is_valid_name(name)) { + pa_proplist_free(p); + CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID); + } s = upload_stream_new(c, &ss, &map, name, length, p); pa_proplist_free(p); @@ -2749,6 +2752,7 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin pa_log_error("Internal sink state is invalid."); pa_tagstruct_putu32(t, pa_sink_get_state(sink)); pa_tagstruct_putu32(t, sink->n_volume_steps); + pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX); } } @@ -2788,6 +2792,7 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s pa_log_error("Internal source state is invalid."); pa_tagstruct_putu32(t, pa_source_get_state(source)); pa_tagstruct_putu32(t, source->n_volume_steps); + pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX); } } @@ -2822,6 +2827,8 @@ static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_car while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) { pa_tagstruct_puts(t, p->name); pa_tagstruct_puts(t, p->description); + pa_tagstruct_putu32(t, p->n_sinks); + pa_tagstruct_putu32(t, p->n_sources); } } @@ -3007,7 +3014,7 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p source_fill_tagstruct(c, reply, source); else if (client) client_fill_tagstruct(c, reply, client); - else if (client) + else if (card) card_fill_tagstruct(c, reply, card); else if (module) module_fill_tagstruct(c, reply, module); @@ -3586,24 +3593,30 @@ static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t } } - CHECK_VALIDITY(c->pstream, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, tag, PA_ERR_INVALID); + if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) { + pa_proplist_free(p); + CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID); + } if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) { playback_stream *s; s = pa_idxset_get_by_index(c->output_streams, idx); - CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); - + if (!s || !playback_stream_isinstance(s)) { + pa_proplist_free(p); + CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY); + } pa_sink_input_update_proplist(s->sink_input, mode, p); } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) { record_stream *s; - s = pa_idxset_get_by_index(c->record_streams, idx); - CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - + if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { + pa_proplist_free(p); + CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY); + } pa_source_output_update_proplist(s->source_output, mode, p); + } else { pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST); @@ -3611,6 +3624,7 @@ static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t } pa_pstream_send_simple_ack(c->pstream, tag); + pa_proplist_free(p); } static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -4066,7 +4080,7 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m); - CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION); + CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION); if (cb(c->protocol, m, c, tag, t) < 0) protocol_error(c); @@ -4144,17 +4158,20 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (playback_stream_isinstance(stream)) { playback_stream *ps = PLAYBACK_STREAM(stream); - if (seek != PA_SEEK_RELATIVE || offset != 0) - pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL); + if (chunk->memblock) { + if (seek != PA_SEEK_RELATIVE || offset != 0) + pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL); - pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); + pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); + } else + pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset+chunk->length, NULL, NULL); } else { upload_stream *u = UPLOAD_STREAM(stream); size_t l; if (!u->memchunk.memblock) { - if (u->length == chunk->length) { + if (u->length == chunk->length && chunk->memblock) { u->memchunk = *chunk; pa_memblock_ref(u->memchunk.memblock); u->length = 0; @@ -4170,17 +4187,22 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (l > chunk->length) l = chunk->length; - if (l > 0) { - void *src, *dst; + void *dst; dst = pa_memblock_acquire(u->memchunk.memblock); - src = pa_memblock_acquire(chunk->memblock); - memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length, - (uint8_t*) src+chunk->index, l); + if (chunk->memblock) { + void *src; + src = pa_memblock_acquire(chunk->memblock); + + memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length, + (uint8_t*) src + chunk->index, l); + + pa_memblock_release(chunk->memblock); + } else + pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec); pa_memblock_release(u->memchunk.memblock); - pa_memblock_release(chunk->memblock); u->memchunk.length += l; u->length -= l; diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7ff8edc9..ef1105ba 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -832,8 +832,8 @@ static int do_read(pa_pstream *p) { ntohl(p->read.shm_info[PA_PSTREAM_SHM_INDEX]), ntohl(p->read.shm_info[PA_PSTREAM_SHM_LENGTH])))) { - pa_log_warn("Failed to import memory block."); - return -1; + if (pa_log_ratelimit()) + pa_log_debug("Failed to import memory block."); } if (p->recieve_memblock_callback) { @@ -842,7 +842,7 @@ static int do_read(pa_pstream *p) { chunk.memblock = b; chunk.index = 0; - chunk.length = pa_memblock_get_length(b); + chunk.length = b ? pa_memblock_get_length(b) : ntohl(p->read.shm_info[PA_PSTREAM_SHM_LENGTH]); offset = (int64_t) ( (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | @@ -857,7 +857,8 @@ static int do_read(pa_pstream *p) { p->recieve_memblock_callback_userdata); } - pa_memblock_unref(b); + if (b) + pa_memblock_unref(b); } goto frame_done; diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c index 5fc6da2b..dcbd1184 100644 --- a/src/pulsecore/rtclock.c +++ b/src/pulsecore/rtclock.c @@ -141,3 +141,11 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) { return tv; } + +pa_usec_t pa_timespec_load(const struct timespec *ts) { + pa_assert(ts); + + return + (pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC + + (pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC; +} diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h index 281461df..03cc1c72 100644 --- a/src/pulsecore/rtclock.h +++ b/src/pulsecore/rtclock.h @@ -42,4 +42,6 @@ void pa_rtclock_hrtimer_enable(void); struct timeval* pa_rtclock_from_wallclock(struct timeval *tv); +pa_usec_t pa_timespec_load(const struct timespec *ts); + #endif diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c index 543262bc..01dfd620 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -50,29 +50,39 @@ #include <pulsecore/rtsig.h> #include <pulsecore/flist.h> #include <pulsecore/core-util.h> - #include <pulsecore/winsock.h> +#include <pulsecore/ratelimit.h> #include "rtpoll.h" +/* #define DEBUG_TIMING */ + struct pa_rtpoll { struct pollfd *pollfd, *pollfd2; unsigned n_pollfd_alloc, n_pollfd_used; - pa_bool_t timer_enabled; struct timeval next_elapse; + pa_bool_t timer_enabled:1; - pa_bool_t scan_for_dead; - pa_bool_t running, installed, rebuild_needed, quit; + pa_bool_t scan_for_dead:1; + pa_bool_t running:1; + pa_bool_t installed:1; + pa_bool_t rebuild_needed:1; + pa_bool_t quit:1; #ifdef HAVE_PPOLL + pa_bool_t timer_armed:1; +#ifdef __linux__ + pa_bool_t dont_use_ppoll:1; +#endif int rtsig; sigset_t sigset_unblocked; timer_t timer; - pa_bool_t timer_armed; -#ifdef __linux__ - pa_bool_t dont_use_ppoll; #endif + +#ifdef DEBUG_TIMING + pa_usec_t timestamp; + pa_usec_t slept, awake; #endif PA_LLIST_HEAD(pa_rtpoll_item, items); @@ -149,6 +159,11 @@ pa_rtpoll *pa_rtpoll_new(void) { PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items); +#ifdef DEBUG_TIMING + p->timestamp = pa_rtclock_usec(); + p->slept = p->awake = 0; +#endif + return p; } @@ -156,7 +171,7 @@ void pa_rtpoll_install(pa_rtpoll *p) { pa_assert(p); pa_assert(!p->installed); - p->installed = 1; + p->installed = TRUE; #ifdef HAVE_PPOLL # ifdef __linux__ @@ -377,6 +392,14 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now)); } +#ifdef DEBUG_TIMING + { + pa_usec_t now = pa_rtclock_usec(); + p->awake = now - p->timestamp; + p->timestamp = now; + } +#endif + /* OK, now let's sleep */ #ifdef HAVE_PPOLL @@ -396,6 +419,18 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { #endif r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1); +#ifdef DEBUG_TIMING + { + pa_usec_t now = pa_rtclock_usec(); + p->slept = now - p->timestamp; + p->timestamp = now; + + pa_log("Process time %llu ms; sleep time %llu ms", + (unsigned long long) (p->awake / PA_USEC_PER_MSEC), + (unsigned long long) (p->slept / PA_USEC_PER_MSEC)); + } +#endif + if (r < 0) { if (errno == EAGAIN || errno == EINTR) r = 0; diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index c59d247c..b8c5f786 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -70,14 +70,14 @@ /* We now put this SHM marker at the end of each segment. It's * optional, to not require a reboot when upgrading, though */ -struct shm_marker PA_GCC_PACKED { +struct shm_marker { pa_atomic_t marker; /* 0xbeefcafe */ pa_atomic_t pid; uint64_t _reserved1; uint64_t _reserved2; uint64_t _reserved3; uint64_t _reserved4; -}; +} PA_GCC_PACKED; static char *segment_name(char *fn, size_t l, unsigned id) { pa_snprintf(fn, l, "/pulse-shm-%u", id); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 4f39d671..7441e971 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -1846,6 +1846,9 @@ void pa_sink_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t m pa_sink_assert_ref(s); + pa_assert(!min_latency || !max_latency || + min_latency <= max_latency); + s->thread_info.min_latency = min_latency; s->thread_info.max_latency = max_latency; diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index 6739effd..dc23bff6 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -278,7 +278,11 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size pa_make_fd_cloexec(c->fd); +#ifdef HAVE_IPV6 if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) +#else + if (sa->sa_family == AF_INET) +#endif pa_make_tcp_socket_low_delay(c->fd); else pa_make_socket_low_delay(c->fd); @@ -353,6 +357,7 @@ void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on c->userdata = userdata; } +#ifdef HAVE_IPV6 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) { struct sockaddr_in6 sa; @@ -367,6 +372,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[ return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } +#endif #ifdef HAVE_LIBASYNCNS @@ -470,7 +476,15 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port); memset(&hints, 0, sizeof(hints)); - hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC); + if (a.type == PA_PARSED_ADDRESS_TCP4) + hints.ai_family = PF_INET; +#ifdef HAVE_IPV6 + else if (a.type == PA_PARSED_ADDRESS_TCP6) + hints.ai_family = PF_INET6; +#endif + else + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; #if defined(HAVE_LIBASYNCNS) @@ -509,11 +523,13 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam struct hostent *host = NULL; struct sockaddr_in s; +#ifdef HAVE_IPV6 /* FIXME: PF_INET6 support */ if (hints.ai_family == PF_INET6) { pa_log_error("IPv6 is not supported on Windows"); goto finish; } +#endif host = gethostbyname(a.path_or_host); if (!host) { diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h index 9ceeaddc..ed36400c 100644 --- a/src/pulsecore/socket-client.h +++ b/src/pulsecore/socket-client.h @@ -35,7 +35,9 @@ typedef struct pa_socket_client pa_socket_client; typedef void (*pa_socket_client_cb_t)(pa_socket_client *c, pa_iochannel*io, void *userdata); pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port); +#ifdef HAVE_IPV6 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port); +#endif pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename); pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char *a, uint16_t default_port); diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index a600e0a6..19c2fd09 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -289,6 +289,7 @@ fail: return NULL; } +#ifdef HAVE_IPV6 pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service) { pa_socket_server *ss; int fd = -1; @@ -347,6 +348,7 @@ fail: return NULL; } +#endif pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { pa_assert(m); @@ -355,12 +357,14 @@ pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_ return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service); } +#ifdef HAVE_IPV6 pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { pa_assert(m); pa_assert(port > 0); return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service); } +#endif pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { pa_assert(m); @@ -369,12 +373,14 @@ pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t por return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service); } +#ifdef HAVE_IPV6 pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { pa_assert(m); pa_assert(port > 0); return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service); } +#endif pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in_addr ipv4; @@ -389,6 +395,7 @@ pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const cha return NULL; } +#ifdef HAVE_IPV6 pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in6_addr ipv6; @@ -401,6 +408,7 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha return NULL; } +#endif static void socket_server_free(pa_socket_server*s) { pa_assert(s); @@ -441,6 +449,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { pa_assert(l > 0); switch (s->type) { +#ifdef HAVE_IPV6 case SOCKET_SERVER_IPV6: { struct sockaddr_in6 sa; socklen_t sa_len = sizeof(sa); @@ -476,6 +485,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { return c; } +#endif case SOCKET_SERVER_IPV4: { struct sockaddr_in sa; diff --git a/src/pulsecore/socket-server.h b/src/pulsecore/socket-server.h index 1edfb432..b9a2c40e 100644 --- a/src/pulsecore/socket-server.h +++ b/src/pulsecore/socket-server.h @@ -34,13 +34,15 @@ typedef struct pa_socket_server pa_socket_server; pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename); pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service); +#ifdef HAVE_IPV6 +pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service); +#endif void pa_socket_server_unref(pa_socket_server*s); pa_socket_server* pa_socket_server_ref(pa_socket_server *s); diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c index a0920025..e44f6460 100644 --- a/src/pulsecore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -93,7 +93,9 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { union { struct sockaddr sa; struct sockaddr_in in; +#ifdef HAVE_IPV6 struct sockaddr_in6 in6; +#endif #ifdef HAVE_SYS_UN_H struct sockaddr_un un; #endif @@ -112,6 +114,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { ip & 0xFF, ntohs(sa.in.sin_port)); return; +#ifdef HAVE_IPV6 } else if (sa.sa.sa_family == AF_INET6) { char buf[INET6_ADDRSTRLEN]; const char *res; @@ -121,6 +124,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { pa_snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port)); return; } +#endif #ifdef HAVE_SYS_UN_H } else if (sa.sa.sa_family == AF_UNIX) { pa_snprintf(c, l, "UNIX socket client"); @@ -298,8 +302,10 @@ pa_bool_t pa_socket_address_is_local(const struct sockaddr *sa) { case AF_INET: return ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK; +#ifdef HAVE_IPV6 case AF_INET6: return memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0; +#endif default: return FALSE; @@ -311,7 +317,9 @@ pa_bool_t pa_socket_is_local(int fd) { union { struct sockaddr sa; struct sockaddr_in in; +#ifdef HAVE_IPV6 struct sockaddr_in6 in6; +#endif #ifdef HAVE_SYS_UN_H struct sockaddr_un un; #endif diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 0009d85c..c0d6d9ea 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -1120,6 +1120,9 @@ void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec pa_source_assert_ref(s); + pa_assert(!min_latency || !max_latency || + min_latency <= max_latency); + s->thread_info.min_latency = min_latency; s->thread_info.max_latency = max_latency; |