From 3e10f3f4e3bde6bb772eab70a1008895a302494f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Jun 2009 23:50:43 +0200 Subject: tdb: include signal.h before tdb.h for compat reasons --- src/pulsecore/database-tdb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/database-tdb.c b/src/pulsecore/database-tdb.c index c35fd81f..b79d2837 100644 --- a/src/pulsecore/database-tdb.c +++ b/src/pulsecore/database-tdb.c @@ -26,6 +26,9 @@ #include #include #include + +/* Some versions of tdb lack inclusion of signal.h in the header files but use sigatomic_t */ +#include #include #include -- cgit From 00797b8b6ea7978f862facb7181fb04895caf23c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Jun 2009 19:05:07 +0200 Subject: core: add a suspend cause flags field --- src/pulsecore/card.c | 7 ++++--- src/pulsecore/card.h | 2 +- src/pulsecore/cli-command.c | 8 ++++---- src/pulsecore/cli-text.c | 10 ++++++++++ src/pulsecore/core.h | 10 ++++++++++ src/pulsecore/protocol-esound.c | 4 ++-- src/pulsecore/protocol-native.c | 8 ++++---- src/pulsecore/sink.c | 16 +++++++++++++--- src/pulsecore/sink.h | 5 +++-- src/pulsecore/source.c | 16 +++++++++++++--- src/pulsecore/source.h | 5 +++-- 11 files changed, 67 insertions(+), 24 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 8101a92e..59b8cda6 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -244,19 +244,20 @@ int pa_card_set_profile(pa_card *c, const char *name, pa_bool_t save) { return 0; } -int pa_card_suspend(pa_card *c, pa_bool_t suspend) { +int pa_card_suspend(pa_card *c, pa_bool_t suspend, pa_suspend_cause_t cause) { pa_sink *sink; pa_source *source; uint32_t idx; int ret = 0; pa_assert(c); + pa_assert(cause != 0); for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) - ret -= pa_sink_suspend(sink, suspend) < 0; + ret -= pa_sink_suspend(sink, suspend, cause) < 0; for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) - ret -= pa_source_suspend(source, suspend) < 0; + ret -= pa_source_suspend(source, suspend, cause) < 0; return ret; } diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index 3b7608f6..415ab678 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -99,6 +99,6 @@ void pa_card_free(pa_card *c); int pa_card_set_profile(pa_card *c, const char *name, pa_bool_t save); -int pa_card_suspend(pa_card *c, pa_bool_t suspend); +int pa_card_suspend(pa_card *c, pa_bool_t suspend, pa_suspend_cause_t cause); #endif diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index dad647a8..644de96e 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -1278,7 +1278,7 @@ static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *b return -1; } - if ((r = pa_sink_suspend(sink, suspend)) < 0) + if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0) pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r)); return 0; @@ -1314,7 +1314,7 @@ static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf return -1; } - if ((r = pa_source_suspend(source, suspend)) < 0) + if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0) pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r)); return 0; @@ -1339,10 +1339,10 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, p return -1; } - if ((r = pa_sink_suspend_all(c, suspend)) < 0) + if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0) pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r)); - if ((r = pa_source_suspend_all(c, suspend)) < 0) + if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0) pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r)); return 0; diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index 604678be..bc863f05 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -232,6 +232,7 @@ char *pa_sink_list_to_string(pa_core *c) { "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s%s\n" "\tstate: %s\n" + "\tsuspend cause: %s%s%s%s\n" "\tvolume: %s%s%s\n" "\t balance %0.2f\n" "\tbase volume: %s%s%s\n" @@ -258,6 +259,10 @@ char *pa_sink_list_to_string(pa_core *c) { sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME " : "", sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "", sink_state_to_string(pa_sink_get_state(sink)), + sink->suspend_cause & PA_SUSPEND_USER ? "USER " : "", + sink->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "", + sink->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "", + sink->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "", pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE, FALSE)), sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "", sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_sink_get_volume(sink, FALSE, FALSE)) : "", @@ -335,6 +340,7 @@ char *pa_source_list_to_string(pa_core *c) { "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s\n" "\tstate: %s\n" + "\tsuspend cause: %s%s%s%s\n" "\tvolume: %s%s%s\n" "\t balance %0.2f\n" "\tbase volume: %s%s%s\n" @@ -358,6 +364,10 @@ char *pa_source_list_to_string(pa_core *c) { source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", source->flags & PA_SOURCE_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "", source_state_to_string(pa_source_get_state(source)), + source->suspend_cause & PA_SUSPEND_USER ? "USER " : "", + source->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "", + source->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "", + source->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "", pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)), source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "", source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_source_get_volume(source, FALSE)) : "", diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index c6794445..09a880c4 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -27,6 +27,16 @@ typedef struct pa_core pa_core; +/* This is a bitmask that encodes the cause why a sink/source is + * suspended. */ +typedef enum pa_suspend_cause { + PA_SUSPEND_USER = 1, /* Exposed to the user via some protocol */ + PA_SUSPEND_APPLICATION = 2, /* Used by the device reservation logic */ + PA_SUSPEND_IDLE = 4, /* Used by module-suspend-on-idle */ + PA_SUSPEND_SESSION = 8, /* Used by module-hal for mark inactive sessions */ + PA_SUSPEND_ALL = 0xFFFF /* Magic cause that can be used to resume forcibly */ +} pa_suspend_cause_t; + #include #include #include diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 7e7126ea..ad7cd045 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -947,10 +947,10 @@ static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const connection_write(c, &ok, sizeof(int32_t)); if (request == ESD_PROTO_STANDBY) - ok = pa_sink_suspend_all(c->protocol->core, TRUE) >= 0; + ok = pa_sink_suspend_all(c->protocol->core, TRUE, PA_SUSPEND_USER) >= 0; else { pa_assert(request == ESD_PROTO_RESUME); - ok = pa_sink_suspend_all(c->protocol->core, FALSE) >= 0; + ok = pa_sink_suspend_all(c->protocol->core, FALSE, PA_SUSPEND_USER) >= 0; } connection_write(c, &ok, sizeof(int32_t)); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index d4a9952a..e9e2d601 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -4098,7 +4098,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming"); - if (pa_sink_suspend_all(c->protocol->core, b) < 0) { + if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } @@ -4112,7 +4112,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); - if (pa_sink_suspend(sink, b) < 0) { + if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } @@ -4125,7 +4125,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa pa_log_debug("%s all sources", b ? "Suspending" : "Resuming"); - if (pa_source_suspend_all(c->protocol->core, b) < 0) { + if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } @@ -4140,7 +4140,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); - if (pa_source_suspend(source, b) < 0) { + if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 28b3440c..3c4adc6c 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -190,6 +190,7 @@ pa_sink* pa_sink_new( s->core = core; s->state = PA_SINK_INIT; s->flags = flags; + s->suspend_cause = 0; s->name = pa_xstrdup(name); s->proplist = pa_proplist_copy(data->proplist); s->driver = pa_xstrdup(pa_path_get_filename(data->driver)); @@ -499,11 +500,19 @@ int pa_sink_update_status(pa_sink*s) { } /* Called from main context */ -int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) { +int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); + pa_assert(cause != 0); if (suspend) + s->suspend_cause |= cause; + else + s->suspend_cause &= ~cause; + + pa_log_debug("Suspend cause of sink %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming"); + + if (s->suspend_cause) return sink_set_state(s, PA_SINK_SUSPENDED); else return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE); @@ -1823,17 +1832,18 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse } /* Called from main thread */ -int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) { +int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) { pa_sink *sink; uint32_t idx; int ret = 0; pa_core_assert_ref(c); + pa_assert(cause != 0); for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx))) { int r; - if ((r = pa_sink_suspend(sink, suspend)) < 0) + if ((r = pa_sink_suspend(sink, suspend, cause)) < 0) ret = r; } diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index e33b3cfc..4dce3f93 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -56,6 +56,7 @@ struct pa_sink { pa_core *core; pa_sink_state_t state; pa_sink_flags_t flags; + pa_suspend_cause_t suspend_cause; char *name; char *driver; /* may be NULL */ @@ -252,8 +253,8 @@ size_t pa_sink_get_max_rewind(pa_sink *s); size_t pa_sink_get_max_request(pa_sink *s); int pa_sink_update_status(pa_sink*s); -int pa_sink_suspend(pa_sink *s, pa_bool_t suspend); -int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend); +int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause); +int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause); void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume); void pa_sink_propagate_flat_volume(pa_sink *s); diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 8aeb5606..4ade18f6 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -180,6 +180,7 @@ pa_source* pa_source_new( s->core = core; s->state = PA_SOURCE_INIT; s->flags = flags; + s->suspend_cause = 0; s->name = pa_xstrdup(name); s->proplist = pa_proplist_copy(data->proplist); s->driver = pa_xstrdup(pa_path_get_filename(data->driver)); @@ -427,13 +428,21 @@ int pa_source_update_status(pa_source*s) { } /* Called from main context */ -int pa_source_suspend(pa_source *s, pa_bool_t suspend) { +int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) { pa_source_assert_ref(s); pa_assert(PA_SOURCE_IS_LINKED(s->state)); + pa_assert(cause != 0); if (s->monitor_of) return -PA_ERR_NOTSUPPORTED; + if (suspend) + s->suspend_cause |= cause; + else + s->suspend_cause &= ~cause; + + pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming"); + if (suspend) return source_set_state(s, PA_SOURCE_SUSPENDED); else @@ -1032,12 +1041,13 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_ } /* Called from main thread */ -int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) { +int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) { uint32_t idx; pa_source *source; int ret = 0; pa_core_assert_ref(c); + pa_assert(cause != 0); for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) { int r; @@ -1045,7 +1055,7 @@ int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) { if (source->monitor_of) continue; - if ((r = pa_source_suspend(source, suspend)) < 0) + if ((r = pa_source_suspend(source, suspend, cause)) < 0) ret = r; } diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 2978f57b..1fbed70e 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -58,6 +58,7 @@ struct pa_source { pa_core *core; pa_source_state_t state; pa_source_flags_t flags; + pa_suspend_cause_t suspend_cause; char *name; char *driver; /* may be NULL */ @@ -231,8 +232,8 @@ void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t size_t pa_source_get_max_rewind(pa_source *s); int pa_source_update_status(pa_source*s); -int pa_source_suspend(pa_source *s, pa_bool_t suspend); -int pa_source_suspend_all(pa_core *c, pa_bool_t suspend); +int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause); +int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause); void pa_source_set_volume(pa_source *source, const pa_cvolume *volume); const pa_cvolume *pa_source_get_volume(pa_source *source, pa_bool_t force_refresh); -- cgit From 496be212ad645999647c432a856c906b86d41487 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 Jun 2009 15:30:24 +0200 Subject: hashmap: introduce PA_HASHMAP_FOREACH macro --- src/pulsecore/hashmap.h | 4 ++++ src/pulsecore/idxset.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index 08e18ead..828e2448 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -65,4 +65,8 @@ void *pa_hashmap_steal_first(pa_hashmap *h); /* Return the oldest entry in the hashmap */ void* pa_hashmap_first(pa_hashmap *h); +/* A macro to ease iteration through all entries */ +#define PA_HASHMAP_FOREACH(e, h, state) \ + for ((state) = NULL, (e) = pa_hashmap_iterate((h), &(state), NULL); (e); (e) = pa_hashmap_iterate((h), &(state), NULL)) + #endif diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h index 6b9ff472..a6179fcf 100644 --- a/src/pulsecore/idxset.h +++ b/src/pulsecore/idxset.h @@ -103,7 +103,7 @@ unsigned pa_idxset_size(pa_idxset*s); /* Return TRUE of the idxset is empty */ pa_bool_t pa_idxset_isempty(pa_idxset *s); - +/* A macro to ease iteration through all entries */ #define PA_IDXSET_FOREACH(e, s, idx) \ for ((e) = pa_idxset_first((s), &(idx)); (e); (e) = pa_idxset_next((s), &(idx))) -- cgit From 69eab1e057e000951516cfd381846c33abc8aaf1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 Jun 2009 15:31:46 +0200 Subject: core: suppress suspending/resume when we are already in the right state --- src/pulsecore/sink.c | 3 +++ src/pulsecore/source.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 3c4adc6c..a087e42d 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -510,6 +510,9 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) { else s->suspend_cause &= ~cause; + if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause) + return 0; + pa_log_debug("Suspend cause of sink %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming"); if (s->suspend_cause) diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 4ade18f6..abb5f4d1 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -441,6 +441,9 @@ int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) else s->suspend_cause &= ~cause; + if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause) + return 0; + pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming"); if (suspend) -- cgit From d1646f78af6a43928cb0cd6b3e8d45578c489cb1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 Jun 2009 15:32:45 +0200 Subject: core: monitor sources need to inherit the suspend cause from their sinks --- src/pulsecore/sink.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index a087e42d..141084d6 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -505,10 +505,13 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) { pa_assert(PA_SINK_IS_LINKED(s->state)); pa_assert(cause != 0); - if (suspend) + if (suspend) { s->suspend_cause |= cause; - else + s->monitor_source->suspend_cause |= cause; + } else { s->suspend_cause &= ~cause; + s->monitor_source->suspend_cause &= ~cause; + } if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause) return 0; -- cgit From 8eaea3aa6471b7d0e78d110752847db5b213c85a Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 14 May 2009 09:42:52 +0300 Subject: optimization: Optimized pa_sink_render_full. This is finally the latest version of the patch. --- src/pulsecore/sink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 141084d6..db9b4f3a 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -1025,14 +1025,13 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { pa_memchunk chunk; size_t l, d; pa_memchunk_make_writable(result, length); - result->length = length; l = length - result->length; d = result->index + result->length; while (l > 0) { chunk = *result; - chunk.index += d; - chunk.length -= d - result->index; + chunk.index = d; + chunk.length = l; pa_sink_render_into(s, &chunk); -- cgit From 587fc2ab1c7b53ddd28f35e19aad55caa804de1f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Jun 2009 00:02:15 +0200 Subject: core: make sure soft mute status stays in sync with hw mute status This should close rhbz #494851, mandriva bz #51234. Probably the same as our own #572, launchpad #352732. --- src/pulsecore/sink.c | 6 +++++- src/pulsecore/source.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index db9b4f3a..5d54d839 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -1365,8 +1365,12 @@ pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) { pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0); - if (old_muted != s->muted) + if (old_muted != s->muted) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + /* Make sure the soft mute status stays in sync */ + pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0); + } } return s->muted; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index abb5f4d1..53697c57 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -768,8 +768,12 @@ pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) { pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0); - if (old_muted != s->muted) + if (old_muted != s->muted) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + /* Make sure the soft mute status stays in sync */ + pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0); + } } return s->muted; -- cgit From e7a6d53118315ff12896707e42528bda5e5d9eab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Jun 2009 00:12:20 +0200 Subject: core: replace tabs by spaces --- src/pulsecore/sink.c | 62 ++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 5d54d839..13f0e11e 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -973,21 +973,21 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { n = fill_mix_info(s, &length1st, info, MAX_MIX_CHANNELS); if (n == 0) { - pa_silence_memchunk_get(&s->core->silence_cache, - s->core->mempool, - result, - &s->sample_spec, - length1st); + pa_silence_memchunk_get(&s->core->silence_cache, + s->core->mempool, + result, + &s->sample_spec, + length1st); } else if (n == 1) { - pa_cvolume volume; + pa_cvolume volume; - *result = info[0].chunk; - pa_memblock_ref(result->memblock); + *result = info[0].chunk; + pa_memblock_ref(result->memblock); - if (result->length > length) - result->length = length; + if (result->length > length) + result->length = length; - pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); + pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) { if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) { @@ -1005,10 +1005,10 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { } else { void *ptr; - result->index = 0; - result->memblock = pa_memblock_new(s->core->mempool, length); + result->index = 0; + result->memblock = pa_memblock_new(s->core->mempool, length); - ptr = pa_memblock_acquire(result->memblock); + ptr = pa_memblock_acquire(result->memblock); result->length = pa_mix(info, n, (uint8_t*) ptr + result->index, length1st, @@ -1022,23 +1022,23 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { inputs_drop(s, info, n, result); if (result->length < length) { - pa_memchunk chunk; - size_t l, d; - pa_memchunk_make_writable(result, length); - - l = length - result->length; - d = result->index + result->length; - while (l > 0) { - chunk = *result; - chunk.index = d; - chunk.length = l; - - pa_sink_render_into(s, &chunk); - - d += chunk.length; - l -= chunk.length; - } - result->length = length; + pa_memchunk chunk; + size_t l, d; + pa_memchunk_make_writable(result, length); + + l = length - result->length; + d = result->index + result->length; + while (l > 0) { + chunk = *result; + chunk.index = d; + chunk.length = l; + + pa_sink_render_into(s, &chunk); + + d += chunk.length; + l -= chunk.length; + } + result->length = length; } pa_sink_unref(s); -- cgit From f13bbd576fef8911275c8eed41ef425163b70398 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Jun 2009 16:58:45 +0200 Subject: prop: introduce new PA_PROP_DEVICE_INTENDED_ROLES property --- src/pulsecore/card.c | 1 + src/pulsecore/sink.c | 17 +++++++++++++++++ src/pulsecore/sink.h | 1 + src/pulsecore/source.c | 1 + 4 files changed, 20 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 59b8cda6..9c16ef2d 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -164,6 +164,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) { pa_device_init_description(c->proplist); pa_device_init_icon(c->proplist, TRUE); + pa_device_init_intended_roles(c->proplist); pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 13f0e11e..1da094af 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -177,6 +177,7 @@ pa_sink* pa_sink_new( pa_device_init_description(data->proplist); pa_device_init_icon(data->proplist, TRUE); + pa_device_init_intended_roles(data->proplist); if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) { pa_xfree(s); @@ -2287,3 +2288,19 @@ pa_bool_t pa_device_init_description(pa_proplist *p) { return FALSE; } + +pa_bool_t pa_device_init_intended_roles(pa_proplist *p) { + const char *s; + pa_assert(p); + + if (pa_proplist_contains(p, PA_PROP_DEVICE_INTENDED_ROLES)) + return TRUE; + + if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) + if (pa_streq(s, "handset") || pa_streq(s, "hands-free")) { + pa_proplist_sets(p, PA_PROP_DEVICE_INTENDED_ROLES, "phone"); + return TRUE; + } + + return FALSE; +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 4dce3f93..0f32d163 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -241,6 +241,7 @@ void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted); pa_bool_t pa_device_init_description(pa_proplist *p); pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink); +pa_bool_t pa_device_init_intended_roles(pa_proplist *p); /**** May be called by everyone, from main context */ diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 53697c57..d35c8523 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -167,6 +167,7 @@ pa_source* pa_source_new( pa_device_init_description(data->proplist); pa_device_init_icon(data->proplist, FALSE); + pa_device_init_intended_roles(data->proplist); if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) { pa_xfree(s); -- cgit From 89e3adf8cd3e0901a786274c584c89dd082eab09 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Jun 2009 18:22:19 +0200 Subject: sample: fix build on BE archs --- src/pulsecore/sample-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index dda38834..5b8ccf59 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -1182,7 +1182,7 @@ pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, case PA_SAMPLE_S24LE: case PA_SAMPLE_S24BE: case PA_SAMPLE_S24_32LE: - case PA_SAMPLE_S24_32RE: + case PA_SAMPLE_S24_32BE: case PA_SAMPLE_FLOAT32LE: case PA_SAMPLE_FLOAT32BE: cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0); -- cgit From 277e8c5ce4cf055108bc8ba17d079a7318932fd2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:01:40 +0200 Subject: idxset: implement pa_idxset_copy() --- src/pulsecore/idxset.c | 14 ++++++++++++++ src/pulsecore/idxset.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index 352ac977..408011f6 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -453,3 +453,17 @@ pa_bool_t pa_idxset_isempty(pa_idxset *s) { return s->n_entries == 0; } + +pa_idxset *pa_idxset_copy(pa_idxset *s) { + pa_idxset *copy; + struct idxset_entry *i; + + pa_assert(s); + + copy = pa_idxset_new(s->hash_func, s->compare_func); + + for (i = s->iterate_list_head; i; i = i->iterate_next) + pa_idxset_put(copy, i->data, NULL); + + return copy; +} diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h index a6179fcf..d1e68c5c 100644 --- a/src/pulsecore/idxset.h +++ b/src/pulsecore/idxset.h @@ -103,6 +103,9 @@ unsigned pa_idxset_size(pa_idxset*s); /* Return TRUE of the idxset is empty */ pa_bool_t pa_idxset_isempty(pa_idxset *s); +/* Duplicate the idxset. This will not copy the actual indexes */ +pa_idxset *pa_idxset_copy(pa_idxset *s); + /* A macro to ease iteration through all entries */ #define PA_IDXSET_FOREACH(e, s, idx) \ for ((e) = pa_idxset_first((s), &(idx)); (e); (e) = pa_idxset_next((s), &(idx))) -- cgit From a1d84e39359fed52770f9d15650aabc6bcce6910 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:02:19 +0200 Subject: hashmap: implement api to iterate a hashmap backwards --- src/pulsecore/hashmap.c | 33 +++++++++++++++++++++++++++++++++ src/pulsecore/hashmap.h | 10 +++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index e957c5ba..b549cb1c 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -237,6 +237,39 @@ at_end: return NULL; } +void *pa_hashmap_iterate_backwards(pa_hashmap *h, void **state, const void **key) { + struct hashmap_entry *e; + + pa_assert(h); + pa_assert(state); + + if (*state == (void*) -1) + goto at_beginning; + + if (!*state && !h->iterate_list_tail) + goto at_beginning; + + e = *state ? *state : h->iterate_list_tail; + + if (e->iterate_previous) + *state = e->iterate_previous; + else + *state = (void*) -1; + + if (key) + *key = e->key; + + return e->value; + +at_beginning: + *state = (void *) -1; + + if (key) + *key = NULL; + + return NULL; +} + void* pa_hashmap_first(pa_hashmap *h) { pa_assert(h); diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index 828e2448..f379fe3c 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -26,7 +26,8 @@ /* Simple Implementation of a hash table. Memory management is the * user's job. It's a good idea to have the key pointer point to a - * string in the value data. */ + * string in the value data. The insertion order is preserved when + * iterating. */ typedef struct pa_hashmap pa_hashmap; @@ -59,6 +60,9 @@ pa_bool_t pa_hashmap_isempty(pa_hashmap *h); returned. */ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void**key); +/* Same as pa_hashmap_iterate() but goes backwards */ +void *pa_hashmap_iterate_backwards(pa_hashmap *h, void **state, const void**key); + /* Remove the oldest entry in the hashmap and return it */ void *pa_hashmap_steal_first(pa_hashmap *h); @@ -69,4 +73,8 @@ void* pa_hashmap_first(pa_hashmap *h); #define PA_HASHMAP_FOREACH(e, h, state) \ for ((state) = NULL, (e) = pa_hashmap_iterate((h), &(state), NULL); (e); (e) = pa_hashmap_iterate((h), &(state), NULL)) +/* A macro to ease iteration through all entries, backwards */ +#define PA_HASHMAP_FOREACH_BACKWARDS(e, h, state) \ + for ((state) = NULL, (e) = pa_hashmap_iterate_backwards((h), &(state), NULL); (e); (e) = pa_hashmap_iterate_backwards((h), &(state), NULL)) + #endif -- cgit From c6830bd9dc53ee745ac331c4ab1c55134562d114 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:02:34 +0200 Subject: hashmap: implement pa_hashmap_last() --- src/pulsecore/hashmap.c | 9 +++++++++ src/pulsecore/hashmap.h | 3 +++ 2 files changed, 12 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index b549cb1c..1fac97eb 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -279,6 +279,15 @@ void* pa_hashmap_first(pa_hashmap *h) { return h->iterate_list_head->value; } +void* pa_hashmap_last(pa_hashmap *h) { + pa_assert(h); + + if (!h->iterate_list_tail) + return NULL; + + return h->iterate_list_tail->value; +} + void* pa_hashmap_steal_first(pa_hashmap *h) { void *data; diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index f379fe3c..ac2092a6 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -69,6 +69,9 @@ void *pa_hashmap_steal_first(pa_hashmap *h); /* Return the oldest entry in the hashmap */ void* pa_hashmap_first(pa_hashmap *h); +/* Return the newest entry in the hashmap */ +void* pa_hashmap_last(pa_hashmap *h); + /* A macro to ease iteration through all entries */ #define PA_HASHMAP_FOREACH(e, h, state) \ for ((state) = NULL, (e) = pa_hashmap_iterate((h), &(state), NULL); (e); (e) = pa_hashmap_iterate((h), &(state), NULL)) -- cgit From 77901e5e624dda97c2dcd2c921a14b77d927ff7e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:08:34 +0200 Subject: channelmap: define a couple of standard channel masks --- src/pulsecore/sample-util.h | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 79af9efc..6a306c11 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -85,4 +86,62 @@ void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn); void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq); +#define PA_CHANNEL_POSITION_MASK_LEFT \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT)) \ + +#define PA_CHANNEL_POSITION_MASK_RIGHT \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT)) + +#define PA_CHANNEL_POSITION_MASK_CENTER \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER)) + +#define PA_CHANNEL_POSITION_MASK_FRONT \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER)) + +#define PA_CHANNEL_POSITION_MASK_REAR \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER)) + +#define PA_CHANNEL_POSITION_MASK_SIDE_OR_TOP_CENTER \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER)) + +#define PA_CHANNEL_POSITION_MASK_TOP \ + (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT) \ + | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER)) + +#define PA_CHANNEL_POSITION_MASK_ALL \ + ((pa_channel_position_mask_t) (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_MAX)-1)) + #endif -- cgit From 7de7b012fd991100abcd031ed06005911cfea8cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:11:47 +0200 Subject: conf-parse: implement .include directive --- src/pulsecore/conf-parser.c | 50 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index a6eb581c..2dc9a223 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -40,19 +40,35 @@ #define COMMENTS "#;\n" /* Run the user supplied parser for an assignment */ -static int next_assignment(const char *filename, unsigned line, const char *section, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { +static int next_assignment( + const char *filename, + unsigned line, + const char *section, + const pa_config_item *t, + const char *lvalue, + const char *rvalue, + void *userdata) { + pa_assert(filename); pa_assert(t); pa_assert(lvalue); pa_assert(rvalue); - for (; t->parse; t++) - if (!t->lvalue || - (pa_streq(lvalue, t->lvalue) && - ((!section && !t->section) || pa_streq(section, t->section)))) - return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata); + for (; t->parse; t++) { + + if (t->lvalue && !pa_streq(lvalue, t->lvalue)) + continue; + + if (t->section && !section) + continue; + + if (t->section && !pa_streq(section, t->section)) + continue; + + return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata); + } - pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", filename, line, lvalue, pa_strnull(section)); + pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", filename, line, lvalue, pa_strna(section)); return -1; } @@ -96,6 +112,25 @@ static int parse_line(const char *filename, unsigned line, char **section, const if (!*b) return 0; + if (pa_startswith(b, ".include ")) { + char *path, *fn; + int r; + + fn = strip(b+9); + if (!pa_is_path_absolute(fn)) { + const char *k; + if ((k = strrchr(filename, '/'))) { + char *dir = pa_xstrndup(filename, k-filename); + fn = path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", dir, fn); + pa_xfree(dir); + } + } + + r = pa_config_parse(fn, NULL, t, userdata); + pa_xfree(path); + return r; + } + if (*b == '[') { size_t k; @@ -135,6 +170,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void if (!f && !(f = fopen(filename, "r"))) { if (errno == ENOENT) { + pa_log_debug("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); r = 0; goto finish; } -- cgit From c5dbf754b578d70d5bf01494fedad74c1829ac38 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:13:01 +0200 Subject: core-util: implement pa_xstrfreev() --- src/pulsecore/core-util.c | 12 ++++++++++++ src/pulsecore/core-util.h | 6 ++++++ 2 files changed, 18 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index b747cd84..0b64edba 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2732,3 +2732,15 @@ void pa_disable_sigpipe(void) { } #endif } + +void pa_xfreev(void**a) { + void **p; + + if (!a) + return; + + for (p = a; *p; p++) + pa_xfree(*p); + + pa_xfree(a); +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index d073b750..5a12ad3f 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -229,4 +229,10 @@ char *pa_realpath(const char *path); void pa_disable_sigpipe(void); +void pa_xfreev(void**a); + +static inline void pa_xstrfreev(char **a) { + pa_xfreev((void**) a); +} + #endif -- cgit From 7fa05bea7e9980243cf58902b9d42e995d1a18bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:13:32 +0200 Subject: core-util: implement pa_split_spaces_strv() --- src/pulsecore/core-util.c | 24 ++++++++++++++++++++++++ src/pulsecore/core-util.h | 2 ++ 2 files changed, 26 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 0b64edba..e39adb12 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2744,3 +2744,27 @@ void pa_xfreev(void**a) { pa_xfree(a); } + +char **pa_split_spaces_strv(const char *s) { + char **t, *e; + unsigned i = 0, n = 8; + const char *state = NULL; + + t = pa_xnew(char*, n); + while ((e = pa_split_spaces(s, &state))) { + t[i++] = e; + + if (i >= n) { + n *= 2; + t = pa_xrenew(char*, t, n); + } + } + + if (i <= 0) { + pa_xfree(t); + return NULL; + } + + t[i] = NULL; + return t; +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 5a12ad3f..d88b7cbb 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -235,4 +235,6 @@ static inline void pa_xstrfreev(char **a) { pa_xfreev((void**) a); } +char **pa_split_spaces_strv(const char *s); + #endif -- cgit From 0fa1ddf8380d6b86bd7e911ac6db7771dcb14dd6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:13:59 +0200 Subject: core-util: implement pa_maybe_prefix_path() --- src/pulsecore/core-util.c | 9 +++++++++ src/pulsecore/core-util.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index e39adb12..a71ba0b0 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2768,3 +2768,12 @@ char **pa_split_spaces_strv(const char *s) { t[i] = NULL; return t; } + +char* pa_maybe_prefix_path(const char *path, const char *prefix) { + pa_assert(path); + + if (pa_is_path_absolute(path)) + return pa_xstrdup(path); + + return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path); +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index d88b7cbb..b841edbb 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -237,4 +237,6 @@ static inline void pa_xstrfreev(char **a) { char **pa_split_spaces_strv(const char *s); +char* pa_maybe_prefix_path(const char *path, const char *prefix); + #endif -- cgit From 325c01bdbc00ad3fcec3982164b100a0bc382109 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:15:36 +0200 Subject: card: some modernizations --- src/pulsecore/card.c | 16 +++++++--------- src/pulsecore/card.h | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 9c16ef2d..5a4f01bd 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -148,15 +148,12 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) { c->save_profile = data->save_profile; if (!c->active_profile && c->profiles) { - void *state = NULL; + void *state; pa_card_profile *p; - while ((p = pa_hashmap_iterate(c->profiles, &state, NULL))) { - if (!c->active_profile || - p->priority > c->active_profile->priority) - + PA_HASHMAP_FOREACH(p, c->profiles, state) + if (!c->active_profile || p->priority > c->active_profile->priority) c->active_profile = p; - } } c->userdata = NULL; @@ -177,7 +174,6 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) { void pa_card_free(pa_card *c) { pa_core *core; - pa_card_profile *profile; pa_assert(c); pa_assert(c->core); @@ -200,8 +196,10 @@ void pa_card_free(pa_card *c) { pa_idxset_free(c->sources, NULL, NULL); if (c->profiles) { - while ((profile = pa_hashmap_steal_first(c->profiles))) - pa_card_profile_free(profile); + pa_card_profile *p; + + while ((p = pa_hashmap_steal_first(c->profiles))) + pa_card_profile_free(p); pa_hashmap_free(c->profiles, NULL, NULL); } diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index 415ab678..aacb24da 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -63,7 +63,7 @@ struct pa_card { pa_hashmap *profiles; pa_card_profile *active_profile; - pa_bool_t save_profile; + pa_bool_t save_profile:1; void *userdata; -- cgit From 4f44fe86fb87076081149b2a2af9392d7fea7c8d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:15:56 +0200 Subject: card: make sure to always hand failure code back in some calls --- src/pulsecore/card.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 5a4f01bd..2f0a3af0 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -212,26 +212,27 @@ void pa_card_free(pa_card *c) { int pa_card_set_profile(pa_card *c, const char *name, pa_bool_t save) { pa_card_profile *profile; + int r; pa_assert(c); if (!c->set_profile) { - pa_log_warn("set_profile() operation not implemented for card %u \"%s\"", c->index, c->name); - return -1; + pa_log_debug("set_profile() operation not implemented for card %u \"%s\"", c->index, c->name); + return -PA_ERR_NOTIMPLEMENTED; } if (!c->profiles) - return -1; + return -PA_ERR_NOENTITY; if (!(profile = pa_hashmap_get(c->profiles, name))) - return -1; + return -PA_ERR_NOENTITY; if (c->active_profile == profile) { c->save_profile = c->save_profile || save; return 0; } - if (c->set_profile(c, profile) < 0) - return -1; + if ((r = c->set_profile(c, profile)) < 0) + return r; pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); @@ -252,11 +253,19 @@ int pa_card_suspend(pa_card *c, pa_bool_t suspend, pa_suspend_cause_t cause) { pa_assert(c); pa_assert(cause != 0); - for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) - ret -= pa_sink_suspend(sink, suspend, cause) < 0; + for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) { + int r; - for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) - ret -= pa_source_suspend(source, suspend, cause) < 0; + if ((r = pa_sink_suspend(sink, suspend, cause)) < 0) + ret = r; + } + + for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { + int r; + + if ((r = pa_source_suspend(source, suspend, cause)) < 0) + ret = r; + } return ret; } -- cgit From 279e0d678e15124f30f3c1a737ddadac1102f735 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:16:13 +0200 Subject: card: get rid of description field which is unused --- src/pulsecore/card.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index aacb24da..2d691b67 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -72,9 +72,8 @@ struct pa_card { typedef struct pa_card_new_data { char *name; - char *description; - pa_proplist *proplist; + const char *driver; pa_module *module; -- cgit From dddb4b02b390cc7d450aa4c198bf2887b01f035e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:16:48 +0200 Subject: gdbm: set default block size to 1K --- src/pulsecore/database-gdbm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/database-gdbm.c b/src/pulsecore/database-gdbm.c index aeaac64b..e65125d3 100644 --- a/src/pulsecore/database-gdbm.c +++ b/src/pulsecore/database-gdbm.c @@ -71,10 +71,13 @@ pa_database* pa_database_open(const char *fn, pa_bool_t for_write) { /* We include the host identifier in the file name because gdbm * files are CPU dependant, and we don't want things to go wrong * if we are on a multiarch system. */ - path = pa_sprintf_malloc("%s."CANONICAL_HOST".gdbm", fn); errno = 0; - f = gdbm_open((char*) path, 0, GDBM_NOLOCK | (for_write ? GDBM_WRCREAT : GDBM_READER), 0644, NULL); + + /* We need to set the block size explicitly here, since otherwise + * gdbm takes the native block size of the underlying file system + * which might be incredibly large. */ + f = gdbm_open((char*) path, 1024, GDBM_NOLOCK | (for_write ? GDBM_WRCREAT : GDBM_READER), 0644, NULL); if (f) pa_log_debug("Opened GDBM database '%s'", path); -- cgit From 1ec33f37d9bc9d3328862d2cd9e155d807888a14 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:17:23 +0200 Subject: pstream: fix s/recieve/receive/ typos --- src/pulsecore/pstream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index ef1105ba..1d4ac177 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -684,7 +684,7 @@ static int do_read(pa_pstream *p) { flags = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]); if (!p->use_shm && (flags & PA_FLAG_SHMMASK) != 0) { - pa_log_warn("Recieved SHM frame on a socket where SHM is disabled."); + pa_log_warn("Received SHM frame on a socket where SHM is disabled."); return -1; } @@ -714,7 +714,7 @@ static int do_read(pa_pstream *p) { length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); if (length > FRAME_SIZE_MAX_ALLOW || length <= 0) { - pa_log_warn("Recieved invalid frame size: %lu", (unsigned long) length); + pa_log_warn("Received invalid frame size: %lu", (unsigned long) length); return -1; } @@ -743,7 +743,7 @@ static int do_read(pa_pstream *p) { if ((flags & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA) { if (length != sizeof(p->read.shm_info)) { - pa_log_warn("Recieved SHM memblock frame with Invalid frame length."); + pa_log_warn("Received SHM memblock frame with Invalid frame length."); return -1; } @@ -758,7 +758,7 @@ static int do_read(pa_pstream *p) { p->read.data = NULL; } else { - pa_log_warn("Recieved memblock frame with invalid flags value."); + pa_log_warn("Received memblock frame with invalid flags value."); return -1; } } -- cgit From e9c70ac41bb86b7778b67284d8a0cae51f6a9ed3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:18:14 +0200 Subject: pdispatch: fix s/recieve/receive/ typos --- src/pulsecore/pdispatch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index d00106b4..4388831a 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -304,7 +304,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, if (command >= PA_COMMAND_MAX || !(p = command_names[command])) pa_snprintf((char*) (p = t), sizeof(t), "%u", command); - pa_log("[%p] Recieved opcode <%s>", pd, p); + pa_log("[%p] Received opcode <%s>", pd, p); } #endif @@ -325,7 +325,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, (*c)(pd, command, tag, ts, userdata); } else { - pa_log("Recieved unsupported command %u", command); + pa_log("Received unsupported command %u", command); goto finish; } -- cgit From 31575f7766d6ff39665b64a3a04412eff1c39957 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 03:45:14 +0200 Subject: alsa: rework mixer logic Completely rework mixer logic. This now allows controlling a full set of elements from a single sink's volume slider/mute button. This also introduces sink and source "ports" that can be used to choose different input or output ports with the UI. (i.e. "mic"/"line-in" or "speaker"/"headphones". The mixer paths and device maps are now configered in external configuration files and can be tweaked as necessary. --- src/pulsecore/cli-command.c | 78 ++++++++++++++++++++-- src/pulsecore/cli-text.c | 36 +++++++++- src/pulsecore/protocol-native.c | 8 +-- src/pulsecore/sink-input.c | 10 +-- src/pulsecore/sink.c | 144 ++++++++++++++++++++++++++++++++++++---- src/pulsecore/sink.h | 46 +++++++++++-- src/pulsecore/source.c | 121 ++++++++++++++++++++++++++++++--- src/pulsecore/source.h | 32 +++++++-- 8 files changed, 425 insertions(+), 50 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 644de96e..e2c3c066 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -125,6 +125,8 @@ static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); /* A method table for all available commands */ @@ -176,10 +178,12 @@ static const struct command commands[] = { { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3}, { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2}, { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index, name)", 3}, + { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index, name)", 3}, + { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index, name)", 3}, { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2}, { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2}, { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2}, - { "set-log-backtrace", pa_cli_command_log_backtrace, "Show bakctrace in log messages (args: frames)", 2}, + { "set-log-backtrace", pa_cli_command_log_backtrace, "Show backtrace in log messages (args: frames)", 2}, { NULL, NULL, NULL, 0 } }; @@ -526,7 +530,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu } pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume); - pa_sink_set_volume(sink, &cvolume, TRUE, TRUE, TRUE); + pa_sink_set_volume(sink, &cvolume, TRUE, TRUE, TRUE, TRUE); return 0; } @@ -604,7 +608,7 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf * } pa_cvolume_set(&cvolume, source->sample_spec.channels, volume); - pa_source_set_volume(source, &cvolume); + pa_source_set_volume(source, &cvolume, TRUE); return 0; } @@ -638,7 +642,7 @@ static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, return -1; } - pa_sink_set_mute(sink, mute); + pa_sink_set_mute(sink, mute, TRUE); return 0; } @@ -672,7 +676,7 @@ static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return -1; } - pa_source_set_mute(source, mute); + pa_source_set_mute(source, mute, TRUE); return 0; } @@ -1476,6 +1480,70 @@ static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *b return 0; } +static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *n, *p; + pa_sink *sink; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); + return -1; + } + + if (!(p = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a profile by its name.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + if (pa_sink_set_port(sink, p, TRUE) < 0) { + pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p); + return -1; + } + + return 0; +} + +static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *n, *p; + pa_source *source; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); + return -1; + } + + if (!(p = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a profile by its name.\n"); + return -1; + } + + if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) { + pa_strbuf_puts(buf, "No source found by this name or index.\n"); + return -1; + } + + if (pa_source_set_port(source, p, TRUE) < 0) { + pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p); + return -1; + } + + return 0; +} + static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_module *m; pa_sink *sink; diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index bc863f05..9395513d 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -139,11 +139,10 @@ char *pa_card_list_to_string(pa_core *c) { if (card->profiles) { pa_card_profile *p; - void *state = NULL; + void *state; pa_strbuf_puts(s, "\tprofiles:\n"); - - while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) + PA_HASHMAP_FOREACH(p, card->profiles, state) pa_strbuf_printf(s, "\t\t%s: %s (priority %u)\n", p->name, p->description, p->priority); } @@ -307,6 +306,22 @@ char *pa_sink_list_to_string(pa_core *c) { t = pa_proplist_to_string_sep(sink->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); + + if (sink->ports) { + pa_device_port *p; + void *state; + + pa_strbuf_puts(s, "\tports:\n"); + PA_HASHMAP_FOREACH(p, sink->ports, state) + pa_strbuf_printf(s, "\t\t%s: %s (priority %u)\n", p->name, p->description, p->priority); + } + + + if (sink->active_port) + pa_strbuf_printf( + s, + "\tactive port: <%s>\n", + sink->active_port->name); } return pa_strbuf_tostring_free(s); @@ -412,6 +427,21 @@ char *pa_source_list_to_string(pa_core *c) { t = pa_proplist_to_string_sep(source->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); + + if (source->ports) { + pa_device_port *p; + void *state; + + pa_strbuf_puts(s, "\tports:\n"); + PA_HASHMAP_FOREACH(p, source->ports, state) + pa_strbuf_printf(s, "\t\t%s: %s (priority %u)\n", p->name, p->description, p->priority); + } + + if (source->active_port) + pa_strbuf_printf( + s, + "\tactive port: <%s>\n", + source->active_port->name); } return pa_strbuf_tostring_free(s); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index e9e2d601..b27346b2 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -3328,9 +3328,9 @@ static void command_set_volume( CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY); if (sink) - pa_sink_set_volume(sink, &volume, TRUE, TRUE, TRUE); + pa_sink_set_volume(sink, &volume, TRUE, TRUE, TRUE, TRUE); else if (source) - pa_source_set_volume(source, &volume); + pa_source_set_volume(source, &volume, TRUE); else if (si) pa_sink_input_set_volume(si, &volume, TRUE, TRUE); @@ -3400,9 +3400,9 @@ static void command_set_mute( CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY); if (sink) - pa_sink_set_mute(sink, mute); + pa_sink_set_mute(sink, mute, TRUE); else if (source) - pa_source_set_mute(source, mute); + pa_source_set_mute(source, mute, TRUE); else if (si) pa_sink_input_set_mute(si, mute, TRUE); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 0d05b00a..a5f96351 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -442,7 +442,7 @@ void pa_sink_input_unlink(pa_sink_input *i) { if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE); } if (i->sink->asyncmsgq) @@ -520,7 +520,7 @@ void pa_sink_input_put(pa_sink_input *i) { if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE); } else pa_sink_input_set_relative_volume(i, &i->virtual_volume); @@ -900,7 +900,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo * volumes and update the flat volume of the sink */ pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, TRUE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, TRUE, FALSE, FALSE); } else { @@ -1159,7 +1159,7 @@ int pa_sink_input_start_move(pa_sink_input *i) { /* We might need to update the sink's volume if we are in flat * volume mode. */ pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE); } pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0); @@ -1252,7 +1252,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { /* We might need to update the sink's volume if we are in flat volume mode. */ pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE); } pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 1da094af..47792293 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -100,11 +100,51 @@ void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) { data->muted = !!mute; } +void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port) { + pa_assert(data); + + pa_xfree(data->active_port); + data->active_port = pa_xstrdup(port); +} + void pa_sink_new_data_done(pa_sink_new_data *data) { pa_assert(data); - pa_xfree(data->name); pa_proplist_free(data->proplist); + + if (data->ports) { + pa_device_port *p; + + while ((p = pa_hashmap_steal_first(data->ports))) + pa_device_port_free(p); + + pa_hashmap_free(data->ports, NULL, NULL); + } + + pa_xfree(data->name); + pa_xfree(data->active_port); +} + +pa_device_port *pa_device_port_new(const char *name, const char *description, size_t extra) { + pa_device_port *p; + + pa_assert(name); + + p = pa_xmalloc(PA_ALIGN(sizeof(pa_device_port)) + extra); + p->name = pa_xstrdup(name); + p->description = pa_xstrdup(description); + + p->priority = 0; + + return p; +} + +void pa_device_port_free(pa_device_port *p) { + pa_assert(p); + + pa_xfree(p->name); + pa_xfree(p->description); + pa_xfree(p); } /* Called from main context */ @@ -118,6 +158,7 @@ static void reset_callbacks(pa_sink *s) { s->set_mute = NULL; s->request_rewind = NULL; s->update_requested_latency = NULL; + s->set_port = NULL; } /* Called from main context */ @@ -152,6 +193,8 @@ pa_sink* pa_sink_new( return NULL; } + /* FIXME, need to free s here on failure */ + pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver)); pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]); @@ -219,6 +262,30 @@ pa_sink* pa_sink_new( s->asyncmsgq = NULL; s->rtpoll = NULL; + /* As a minor optimization we just steal the list instead of + * copying it here */ + s->ports = data->ports; + data->ports = NULL; + + s->active_port = NULL; + s->save_port = FALSE; + + if (data->active_port && s->ports) + if ((s->active_port = pa_hashmap_get(s->ports, data->active_port))) + s->save_port = data->save_port; + + if (!s->active_port && s->ports) { + void *state; + pa_device_port *p; + + PA_HASHMAP_FOREACH(p, s->ports, state) + if (!s->active_port || p->priority > s->active_port->priority) + s->active_port = p; + } + + s->save_volume = data->save_volume; + s->save_muted = data->save_muted; + pa_silence_memchunk_get( &core->silence_cache, core->mempool, @@ -467,6 +534,15 @@ static void sink_free(pa_object *o) { if (s->proplist) pa_proplist_free(s->proplist); + if (s->ports) { + pa_device_port *p; + + while ((p = pa_hashmap_steal_first(s->ports))) + pa_device_port_free(p); + + pa_hashmap_free(s->ports, NULL, NULL); + } + pa_xfree(s); } @@ -485,6 +561,7 @@ void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) { pa_sink_assert_ref(s); s->rtpoll = p; + if (s->monitor_source) pa_source_set_rtpoll(s->monitor_source, p); } @@ -526,15 +603,15 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) { } /* Called from main context */ -pa_queue *pa_sink_move_all_start(pa_sink *s) { - pa_queue *q; +pa_queue *pa_sink_move_all_start(pa_sink *s, pa_queue *q) { pa_sink_input *i, *n; uint32_t idx; pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); - q = pa_queue_new(); + if (!q) + q = pa_queue_new(); for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) { n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)); @@ -1237,7 +1314,7 @@ void pa_sink_propagate_flat_volume(pa_sink *s) { } /* Called from main thread */ -void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg, pa_bool_t become_reference) { +void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg, pa_bool_t become_reference, pa_bool_t save) { pa_bool_t virtual_volume_changed; pa_sink_assert_ref(s); @@ -1248,6 +1325,7 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagat virtual_volume_changed = !pa_cvolume_equal(volume, &s->virtual_volume); s->virtual_volume = *volume; + s->save_volume = (!virtual_volume_changed && s->save_volume) || save; if (become_reference) s->reference_volume = s->virtual_volume; @@ -1318,15 +1396,17 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh, pa_boo } /* Called from main thread */ -void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) { +void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume, pa_bool_t save) { pa_sink_assert_ref(s); /* The sink implementor may call this if the volume changed to make sure everyone is notified */ - - if (pa_cvolume_equal(&s->virtual_volume, new_volume)) + if (pa_cvolume_equal(&s->virtual_volume, new_volume)) { + s->save_volume = s->save_volume || save; return; + } s->reference_volume = s->virtual_volume = *new_volume; + s->save_volume = save; if (s->flags & PA_SINK_FLAT_VOLUME) pa_sink_propagate_flat_volume(s); @@ -1335,7 +1415,7 @@ void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) { } /* Called from main thread */ -void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) { +void pa_sink_set_mute(pa_sink *s, pa_bool_t mute, pa_bool_t save) { pa_bool_t old_muted; pa_sink_assert_ref(s); @@ -1343,6 +1423,7 @@ void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) { old_muted = s->muted; s->muted = mute; + s->save_muted = (old_muted == s->muted && s->save_muted) || save; if (s->set_mute) s->set_mute(s); @@ -1378,15 +1459,19 @@ pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) { } /* Called from main thread */ -void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) { +void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted, pa_bool_t save) { pa_sink_assert_ref(s); /* The sink implementor may call this if the volume changed to make sure everyone is notified */ - if (s->muted == new_muted) + if (s->muted == new_muted) { + s->save_muted = s->save_muted || save; return; + } s->muted = new_muted; + s->save_muted = save; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } @@ -1484,7 +1569,7 @@ unsigned pa_sink_check_suspend(pa_sink *s) { ret = 0; - for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) { + PA_IDXSET_FOREACH(i, s->inputs, idx) { pa_sink_input_state_t st; st = pa_sink_input_get_state(i); @@ -2194,6 +2279,41 @@ size_t pa_sink_get_max_request(pa_sink *s) { return r; } +/* Called from main context */ +int pa_sink_set_port(pa_sink *s, const char *name, pa_bool_t save) { + pa_device_port *port; + + pa_assert(s); + + if (!s->set_port) { + pa_log_debug("set_port() operation not implemented for sink %u \"%s\"", s->index, s->name); + return -PA_ERR_NOTIMPLEMENTED; + } + + if (!s->ports) + return -PA_ERR_NOENTITY; + + if (!(port = pa_hashmap_get(s->ports, name))) + return -PA_ERR_NOENTITY; + + if (s->active_port == port) { + s->save_port = s->save_port || save; + return 0; + } + + if ((s->set_port(s, port)) < 0) + return -PA_ERR_NOENTITY; + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name); + + s->active_port = port; + s->save_port = save; + + return 0; +} + /* Called from main context */ pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) { const char *ff, *c, *t = NULL, *s = "", *profile, *bus; diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 0f32d163..d16fcc01 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -24,6 +24,7 @@ ***/ typedef struct pa_sink pa_sink; +typedef struct pa_device_port pa_device_port; #include @@ -49,11 +50,23 @@ static inline pa_bool_t PA_SINK_IS_LINKED(pa_sink_state_t x) { return x == PA_SINK_RUNNING || x == PA_SINK_IDLE || x == PA_SINK_SUSPENDED; } +struct pa_device_port { + char *name; + char *description; + + unsigned priority; + + /* .. followed by some implementation specific data */ +}; + +#define PA_DEVICE_PORT_DATA(d) ((void*) ((uint8_t*) d + PA_ALIGN(sizeof(pa_device_port)))) + struct pa_sink { pa_msgobject parent; uint32_t index; pa_core *core; + pa_sink_state_t state; pa_sink_flags_t flags; pa_suspend_cause_t suspend_cause; @@ -83,6 +96,9 @@ struct pa_sink { pa_bool_t refresh_volume:1; pa_bool_t refresh_muted:1; + pa_bool_t save_port:1; + pa_bool_t save_volume:1; + pa_bool_t save_muted:1; pa_asyncmsgq *asyncmsgq; pa_rtpoll *rtpoll; @@ -91,6 +107,9 @@ struct pa_sink { pa_usec_t fixed_latency; /* for sinks with PA_SINK_DYNAMIC_LATENCY this is 0 */ + pa_hashmap *ports; + pa_device_port *active_port; + /* Called when the main loop requests a state change. Called from * main loop context. If returns -1 the state change will be * inhibited */ @@ -126,6 +145,10 @@ struct pa_sink { * thread context. */ void (*update_requested_latency)(pa_sink *s); /* dito */ + /* Called whenever the port shall be changed. Called from main + * thread. */ + int (*set_port)(pa_sink *s, pa_device_port *port); /* dito */ + /* Contains copies of the above data so that the real-time worker * thread can work without access locking */ struct { @@ -192,6 +215,9 @@ typedef struct pa_sink_new_data { pa_module *module; pa_card *card; + pa_hashmap *ports; + char *active_port; + pa_sample_spec sample_spec; pa_channel_map channel_map; pa_cvolume volume; @@ -203,6 +229,10 @@ typedef struct pa_sink_new_data { pa_bool_t muted_is_set:1; pa_bool_t namereg_fail:1; + + pa_bool_t save_port:1; + pa_bool_t save_volume:1; + pa_bool_t save_muted:1; } pa_sink_new_data; pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data); @@ -211,6 +241,7 @@ void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_sp void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map); void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume); void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute); +void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port); void pa_sink_new_data_done(pa_sink_new_data *data); /*** To be called exclusively by the sink driver, from main context */ @@ -236,8 +267,8 @@ void pa_sink_detach(pa_sink *s); void pa_sink_attach(pa_sink *s); void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume); -void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume); -void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted); +void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume, pa_bool_t save); +void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted, pa_bool_t save); pa_bool_t pa_device_init_description(pa_proplist *p); pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink); @@ -260,21 +291,23 @@ int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume); void pa_sink_propagate_flat_volume(pa_sink *s); -void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg, pa_bool_t become_reference); +void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg, pa_bool_t become_reference, pa_bool_t save); const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_bool_t force_refresh, pa_bool_t reference); -void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute); +void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute, pa_bool_t save); pa_bool_t pa_sink_get_mute(pa_sink *sink, pa_bool_t force_refresh); pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p); +int pa_sink_set_port(pa_sink *s, const char *name, pa_bool_t save); + unsigned pa_sink_linked_by(pa_sink *s); /* Number of connected streams */ unsigned pa_sink_used_by(pa_sink *s); /* Number of connected streams which are not corked */ unsigned pa_sink_check_suspend(pa_sink *s); /* Returns how many streams are active that don't allow suspensions */ #define pa_sink_get_state(s) ((s)->state) /* Moves all inputs away, and stores them in pa_queue */ -pa_queue *pa_sink_move_all_start(pa_sink *s); +pa_queue *pa_sink_move_all_start(pa_sink *s, pa_queue *q); void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save); void pa_sink_move_all_fail(pa_queue *q); @@ -307,4 +340,7 @@ void pa_sink_invalidate_requested_latency(pa_sink *s); pa_usec_t pa_sink_get_latency_within_thread(pa_sink *s); +pa_device_port *pa_device_port_new(const char *name, const char *description, size_t extra); +void pa_device_port_free(pa_device_port *p); + #endif diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index d35c8523..1e431160 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -93,11 +93,29 @@ void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) { data->muted = !!mute; } +void pa_source_new_data_set_port(pa_source_new_data *data, const char *port) { + pa_assert(data); + + pa_xfree(data->active_port); + data->active_port = pa_xstrdup(port); +} + void pa_source_new_data_done(pa_source_new_data *data) { pa_assert(data); - pa_xfree(data->name); pa_proplist_free(data->proplist); + + if (data->ports) { + pa_device_port *p; + + while ((p = pa_hashmap_steal_first(data->ports))) + pa_device_port_free(p); + + pa_hashmap_free(data->ports, NULL, NULL); + } + + pa_xfree(data->name); + pa_xfree(data->active_port); } /* Called from main context */ @@ -110,6 +128,7 @@ static void reset_callbacks(pa_source *s) { s->get_mute = NULL; s->set_mute = NULL; s->update_requested_latency = NULL; + s->set_port = NULL; } /* Called from main context */ @@ -142,6 +161,8 @@ pa_source* pa_source_new( return NULL; } + /* FIXME, need to free s here on failure */ + pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver)); pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]); @@ -210,6 +231,30 @@ pa_source* pa_source_new( s->asyncmsgq = NULL; s->rtpoll = NULL; + /* As a minor optimization we just steal the list instead of + * copying it here */ + s->ports = data->ports; + data->ports = NULL; + + s->active_port = NULL; + s->save_port = FALSE; + + if (data->active_port && s->ports) + if ((s->active_port = pa_hashmap_get(s->ports, data->active_port))) + s->save_port = data->save_port; + + if (!s->active_port && s->ports) { + void *state; + pa_device_port *p; + + PA_HASHMAP_FOREACH(p, s->ports, state) + if (!s->active_port || p->priority > s->active_port->priority) + s->active_port = p; + } + + s->save_volume = data->save_volume; + s->save_muted = data->save_muted; + pa_silence_memchunk_get( &core->silence_cache, core->mempool, @@ -400,6 +445,15 @@ static void source_free(pa_object *o) { if (s->proplist) pa_proplist_free(s->proplist); + if (s->ports) { + pa_device_port *p; + + while ((p = pa_hashmap_steal_first(s->ports))) + pa_device_port_free(p); + + pa_hashmap_free(s->ports, NULL, NULL); + } + pa_xfree(s); } @@ -472,15 +526,15 @@ int pa_source_sync_suspend(pa_source *s) { } /* Called from main context */ -pa_queue *pa_source_move_all_start(pa_source *s) { - pa_queue *q; +pa_queue *pa_source_move_all_start(pa_source *s, pa_queue *q) { pa_source_output *o, *n; uint32_t idx; pa_source_assert_ref(s); pa_assert(PA_SOURCE_IS_LINKED(s->state)); - q = pa_queue_new(); + if (!q) + q = pa_queue_new(); for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) { n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)); @@ -667,7 +721,7 @@ pa_usec_t pa_source_get_latency_within_thread(pa_source *s) { } /* Called from main thread */ -void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) { +void pa_source_set_volume(pa_source *s, const pa_cvolume *volume, pa_bool_t save) { pa_cvolume old_virtual_volume; pa_bool_t virtual_volume_changed; @@ -680,6 +734,7 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) { old_virtual_volume = s->virtual_volume; s->virtual_volume = *volume; virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume); + s->save_volume = (!virtual_volume_changed && s->save_volume) || save; if (s->set_volume) { pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels); @@ -725,20 +780,24 @@ const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) { } /* Called from main thread */ -void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) { +void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume, pa_bool_t save) { pa_source_assert_ref(s); /* The source implementor may call this if the volume changed to make sure everyone is notified */ - if (pa_cvolume_equal(&s->virtual_volume, new_volume)) + if (pa_cvolume_equal(&s->virtual_volume, new_volume)) { + s->save_volume = s->save_volume || save; return; + } s->virtual_volume = *new_volume; + s->save_volume = save; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } /* Called from main thread */ -void pa_source_set_mute(pa_source *s, pa_bool_t mute) { +void pa_source_set_mute(pa_source *s, pa_bool_t mute, pa_bool_t save) { pa_bool_t old_muted; pa_source_assert_ref(s); @@ -746,6 +805,7 @@ void pa_source_set_mute(pa_source *s, pa_bool_t mute) { old_muted = s->muted; s->muted = mute; + s->save_muted = (old_muted == s->muted && s->save_muted) || save; if (s->set_mute) s->set_mute(s); @@ -781,15 +841,19 @@ pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) { } /* Called from main thread */ -void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) { +void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted, pa_bool_t save) { pa_source_assert_ref(s); /* The source implementor may call this if the mute state changed to make sure everyone is notified */ - if (s->muted == new_muted) + if (s->muted == new_muted) { + s->save_muted = s->save_muted || save; return; + } s->muted = new_muted; + s->save_muted = save; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } @@ -866,7 +930,7 @@ unsigned pa_source_check_suspend(pa_source *s) { ret = 0; - for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) { + PA_IDXSET_FOREACH(o, s->outputs, idx) { pa_source_output_state_t st; st = pa_source_output_get_state(o); @@ -1323,3 +1387,38 @@ size_t pa_source_get_max_rewind(pa_source *s) { return r; } + +/* Called from main context */ +int pa_source_set_port(pa_source *s, const char *name, pa_bool_t save) { + pa_device_port *port; + + pa_assert(s); + + if (!s->set_port) { + pa_log_debug("set_port() operation not implemented for sink %u \"%s\"", s->index, s->name); + return -PA_ERR_NOTIMPLEMENTED; + } + + if (!s->ports) + return -PA_ERR_NOENTITY; + + if (!(port = pa_hashmap_get(s->ports, name))) + return -PA_ERR_NOENTITY; + + if (s->active_port == port) { + s->save_port = s->save_port || save; + return 0; + } + + if ((s->set_port(s, port)) < 0) + return -PA_ERR_NOENTITY; + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name); + + s->active_port = port; + s->save_port = save; + + return 0; +} diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 1fbed70e..7e9fd8b7 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -56,6 +56,7 @@ struct pa_source { uint32_t index; pa_core *core; + pa_source_state_t state; pa_source_flags_t flags; pa_suspend_cause_t suspend_cause; @@ -83,6 +84,10 @@ struct pa_source { pa_bool_t refresh_volume:1; pa_bool_t refresh_muted:1; + pa_bool_t save_port:1; + pa_bool_t save_volume:1; + pa_bool_t save_muted:1; + pa_asyncmsgq *asyncmsgq; pa_rtpoll *rtpoll; @@ -90,6 +95,9 @@ struct pa_source { pa_usec_t fixed_latency; /* for sources with PA_SOURCE_DYNAMIC_LATENCY this is 0 */ + pa_hashmap *ports; + pa_device_port *active_port; + /* Called when the main loop requests a state change. Called from * main loop context. If returns -1 the state change will be * inhibited */ @@ -121,6 +129,10 @@ struct pa_source { * thread context. */ void (*update_requested_latency)(pa_source *s); /* dito */ + /* Called whenever the port shall be changed. Called from main + * thread. */ + int (*set_port)(pa_source *s, pa_device_port *port); /*dito */ + /* Contains copies of the above data so that the real-time worker * thread can work without access locking */ struct { @@ -174,6 +186,9 @@ typedef struct pa_source_new_data { pa_module *module; pa_card *card; + pa_hashmap *ports; + char *active_port; + pa_sample_spec sample_spec; pa_channel_map channel_map; pa_cvolume volume; @@ -185,6 +200,10 @@ typedef struct pa_source_new_data { pa_bool_t channel_map_is_set:1; pa_bool_t namereg_fail:1; + + pa_bool_t save_port:1; + pa_bool_t save_volume:1; + pa_bool_t save_muted:1; } pa_source_new_data; pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data); @@ -193,6 +212,7 @@ void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sampl void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map); void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume); void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute); +void pa_source_new_data_set_port(pa_source_new_data *data, const char *port); void pa_source_new_data_done(pa_source_new_data *data); /*** To be called exclusively by the source driver, from main context */ @@ -217,8 +237,8 @@ void pa_source_detach(pa_source *s); void pa_source_attach(pa_source *s); void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume); -void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume); -void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted); +void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume, pa_bool_t save); +void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted, pa_bool_t save); int pa_source_sync_suspend(pa_source *s); @@ -235,20 +255,22 @@ int pa_source_update_status(pa_source*s); int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause); int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause); -void pa_source_set_volume(pa_source *source, const pa_cvolume *volume); +void pa_source_set_volume(pa_source *source, const pa_cvolume *volume, pa_bool_t save); const pa_cvolume *pa_source_get_volume(pa_source *source, pa_bool_t force_refresh); -void pa_source_set_mute(pa_source *source, pa_bool_t mute); +void pa_source_set_mute(pa_source *source, pa_bool_t mute, pa_bool_t save); pa_bool_t pa_source_get_mute(pa_source *source, pa_bool_t force_refresh); pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p); +int pa_source_set_port(pa_source *s, const char *name, pa_bool_t save); + unsigned pa_source_linked_by(pa_source *s); /* Number of connected streams */ unsigned pa_source_used_by(pa_source *s); /* Number of connected streams that are not corked */ unsigned pa_source_check_suspend(pa_source *s); /* Returns how many streams are active that don't allow suspensions */ #define pa_source_get_state(s) ((pa_source_state_t) (s)->state) /* Moves all inputs away, and stores them in pa_queue */ -pa_queue *pa_source_move_all_start(pa_source *s); +pa_queue *pa_source_move_all_start(pa_source *s, pa_queue *q); void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save); void pa_source_move_all_fail(pa_queue *q); -- cgit From 6d7cf14dbfc6600cea7ae5110af1160b6a6d140e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 04:52:41 +0200 Subject: native: implement command to change sink/source port --- src/pulsecore/native-common.h | 4 +++ src/pulsecore/protocol-native.c | 67 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index d4d7f3ee..f49abb09 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -165,6 +165,10 @@ enum { PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED, PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED, + /* Supported since protocol v16 (0.9.16) */ + PA_COMMAND_SET_SINK_PORT, + PA_COMMAND_SET_SOURCE_PORT, + PA_COMMAND_MAX }; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index b27346b2..92efc9ee 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -284,6 +284,7 @@ static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = NULL, @@ -380,6 +381,9 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile, + [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port, + [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port, + [PA_COMMAND_EXTENSION] = command_extension }; @@ -4195,6 +4199,7 @@ static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_ uint32_t idx = PA_INVALID_INDEX; const char *name = NULL, *profile = NULL; pa_card *card = NULL; + int ret; pa_native_connection_assert_ref(c); pa_assert(t); @@ -4220,11 +4225,69 @@ static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_ CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY); - if (pa_card_set_profile(card, profile, TRUE) < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + if ((ret = pa_card_set_profile(card, profile, TRUE)) < 0) { + pa_pstream_send_error(c->pstream, tag, -ret); + return; + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); + uint32_t idx = PA_INVALID_INDEX; + const char *name = NULL, *port = NULL; + int ret; + + pa_native_connection_assert_ref(c); + pa_assert(t); + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &port) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); return; } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID); + + if (command == PA_COMMAND_SET_SINK_PORT) { + pa_sink *sink; + + if (idx != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK); + + CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); + + if ((ret = pa_sink_set_port(sink, port, TRUE)) < 0) { + pa_pstream_send_error(c->pstream, tag, -ret); + return; + } + } else { + pa_source *source; + + pa_assert(command = PA_COMMAND_SET_SOURCE_PORT); + + if (idx != PA_INVALID_INDEX) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE); + + CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); + + if ((ret = pa_source_set_port(source, port, TRUE)) < 0) { + pa_pstream_send_error(c->pstream, tag, -ret); + return; + } + } + pa_pstream_send_simple_ack(c->pstream, tag); } -- cgit From 46b8ca21d1ef56df298cfa9412e73fdf17cbea49 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jun 2009 23:17:37 +0200 Subject: native-protocol: allow enumerating ports --- src/pulsecore/protocol-native.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 92efc9ee..48f7b135 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2845,6 +2845,23 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin pa_tagstruct_putu32(t, sink->n_volume_steps); pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX); } + + if (c->version >= 16) { + pa_tagstruct_putu32(t, sink->ports ? pa_hashmap_size(sink->ports) : 0); + + if (sink->ports) { + void *state; + pa_device_port *p; + + PA_HASHMAP_FOREACH(p, sink->ports, state) { + pa_tagstruct_puts(t, p->name); + pa_tagstruct_puts(t, p->description); + pa_tagstruct_putu32(t, p->priority); + } + } + + pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL); + } } static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) { @@ -2885,6 +2902,24 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s pa_tagstruct_putu32(t, source->n_volume_steps); pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX); } + + if (c->version >= 16) { + + pa_tagstruct_putu32(t, source->ports ? pa_hashmap_size(source->ports) : 0); + + if (source->ports) { + void *state; + pa_device_port *p; + + PA_HASHMAP_FOREACH(p, source->ports, state) { + pa_tagstruct_puts(t, p->name); + pa_tagstruct_puts(t, p->description); + pa_tagstruct_putu32(t, p->priority); + } + } + + pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL); + } } static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) { -- cgit From 39b37a2bac34df671a3ff5a5d4ea8b4003f09fc9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Jun 2009 03:40:47 +0200 Subject: core: be a bit more verbose when registering a sink/source fails --- src/pulsecore/sink.c | 1 + src/pulsecore/source.c | 1 + 2 files changed, 2 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 47792293..7e4513e7 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -181,6 +181,7 @@ pa_sink* pa_sink_new( s = pa_msgobject_new(pa_sink); if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) { + pa_log_debug("Failed to register name %s.", data->name); pa_xfree(s); return NULL; } diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 1e431160..74f38bc5 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -149,6 +149,7 @@ pa_source* pa_source_new( s = pa_msgobject_new(pa_source); if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) { + pa_log_debug("Failed to register name %s.", data->name); pa_xfree(s); return NULL; } -- cgit From 8fe50b0d7cd4a93be85887bdb7efd2663face50d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Jun 2009 04:38:59 +0200 Subject: alsa,core: include mapping name in description strings --- src/pulsecore/sink.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 7e4513e7..d8f3c7d1 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -2384,30 +2384,35 @@ pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) { } pa_bool_t pa_device_init_description(pa_proplist *p) { - const char *s; + const char *s, *d = NULL, *k; pa_assert(p); if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION)) return TRUE; if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) - if (pa_streq(s, "internal")) { - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio")); - return TRUE; - } + if (pa_streq(s, "internal")) + d = _("Internal Audio"); - if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) - if (pa_streq(s, "modem")) { - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Modem")); - return TRUE; - } + if (!d) + if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) + if (pa_streq(s, "modem")) + d = _("Modem"); - if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) { - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); - return TRUE; - } + if (!d) + d = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME); - return FALSE; + if (!d) + return FALSE; + + k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION); + + if (d && k) + pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k); + else if (d) + pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d); + + return TRUE; } pa_bool_t pa_device_init_intended_roles(pa_proplist *p) { -- cgit From 8474fd7c62712470465800ddccd6ea291d04151e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Jun 2009 04:19:08 +0200 Subject: core: ask RealtimeKit for RT scheduling --- src/pulsecore/core-util.c | 96 ++++++++++++++++++----- src/pulsecore/rtkit.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++ src/pulsecore/rtkit.h | 62 +++++++++++++++ 3 files changed, 329 insertions(+), 18 deletions(-) create mode 100644 src/pulsecore/rtkit.c create mode 100644 src/pulsecore/rtkit.h (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index a71ba0b0..1fdd1890 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -50,6 +50,10 @@ #ifdef HAVE_SCHED_H #include + +#if defined(__linux__) && !defined(SCHED_RESET_ON_FORK) +#define SCHED_RESET_ON_FORK 0x40000000 +#endif #endif #ifdef HAVE_SYS_RESOURCE_H @@ -92,6 +96,10 @@ #include #endif +#ifdef HAVE_DBUS +#include "rtkit.h" +#endif + #include #include #include @@ -552,16 +560,68 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } +static int set_scheduler(int rtprio) { + struct sched_param sp; + int r; +#ifdef HAVE_DBUS + DBusError error; + DBusConnection *bus; + + dbus_error_init(&error); +#endif + + pa_zero(sp); + sp.sched_priority = rtprio; + +#ifdef SCHED_RESET_ON_FORK + if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) { + pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked."); + return 0; + } +#endif + + if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) { + pa_log_debug("SCHED_RR worked."); + return 0; + } + +#ifdef HAVE_DBUS + /* Try to talk to RealtimeKit */ + + if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { + pa_log("Failed to connect to system bus: %s\n", error.message); + dbus_error_free(&error); + errno = -EIO; + return -1; + } + + r = rtkit_make_realtime(bus, 0, rtprio); + dbus_connection_unref(bus); + + if (r >= 0) { + pa_log_debug("RealtimeKit worked."); + return 0; + } + + errno = -r; +#else + errno = r; +#endif + + return -1; +} + /* Make the current thread a realtime thread, and acquire the highest * rtprio we can get that is less or equal the specified parameter. If * the thread is already realtime, don't do anything. */ int pa_make_realtime(int rtprio) { #ifdef _POSIX_PRIORITY_SCHEDULING - struct sched_param sp; int r, policy; + struct sched_param sp; + int rtprio_try; - memset(&sp, 0, sizeof(sp)); + pa_zero(sp); policy = 0; if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { @@ -569,29 +629,29 @@ int pa_make_realtime(int rtprio) { return -1; } - if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) { - pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority); +#ifdef SCHED_RESET_ON_FORK + policy &= ~SCHED_RESET_ON_FORK; +#endif + + if ((policy == SCHED_FIFO || policy == SCHED_RR) && sp.sched_priority >= rtprio) { + pa_log_info("Thread already being scheduled with SCHED_FIFO/SCHED_RR with priority %i.", sp.sched_priority); return 0; } - sp.sched_priority = rtprio; - if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) { - - while (sp.sched_priority > 1) { - sp.sched_priority --; + if (set_scheduler(rtprio) >= 0) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio); + return 0; + } - if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) == 0) { - pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp.sched_priority, rtprio); - return 0; - } + for (rtprio_try = rtprio-1; rtprio_try >= 1; rtprio_try--) { + if (set_scheduler(rtprio_try)) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", rtprio_try, rtprio); + return 0; } - - pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r)); - return -1; } - pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority); - return 0; + pa_log_warn("Failed to acquire real-time scheduling: %s", pa_cstrerror(r)); + return -1; #else errno = ENOTSUP; diff --git a/src/pulsecore/rtkit.c b/src/pulsecore/rtkit.c new file mode 100644 index 00000000..aecc4e32 --- /dev/null +++ b/src/pulsecore/rtkit.c @@ -0,0 +1,189 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +/*** + Copyright 2009 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include + +#include "rtkit.h" + +#ifdef __linux__ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include + +static pid_t _gettid(void) { + return (pid_t) syscall(SYS_gettid); +} + +static int translate_error(const char *name) { + if (strcmp(name, DBUS_ERROR_NO_MEMORY) == 0) + return -ENOMEM; + if (strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 || + strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0) + return -ENOENT; + if (strcmp(name, DBUS_ERROR_ACCESS_DENIED) == 0 || + strcmp(name, DBUS_ERROR_AUTH_FAILED) == 0) + return -EACCES; + + return -EIO; +} + +int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) { + DBusMessage *m = NULL, *r = NULL; + dbus_uint64_t u64; + dbus_uint32_t u32; + DBusError error; + int ret; + + dbus_error_init(&error); + + if (thread == 0) + thread = _gettid(); + + if (!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.RealtimeKit1", + "MakeThreadRealtime"))) { + ret = -ENOMEM; + goto finish; + } + + u64 = (dbus_uint64_t) thread; + u32 = (dbus_uint32_t) priority; + + if (!dbus_message_append_args( + m, + DBUS_TYPE_UINT64, &u64, + DBUS_TYPE_UINT32, &u32, + DBUS_TYPE_INVALID)) { + ret = -ENOMEM; + goto finish; + } + + if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { + ret = translate_error(error.name); + goto finish; + } + + + if (dbus_set_error_from_message(&error, r)) { + ret = translate_error(error.name); + goto finish; + } + + ret = 0; + +finish: + + if (m) + dbus_message_unref(m); + + if (r) + dbus_message_unref(r); + + dbus_error_free(&error); + + return ret; +} + +int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) { + DBusMessage *m = NULL, *r = NULL; + dbus_uint64_t u64; + dbus_int32_t s32; + DBusError error; + int ret; + + dbus_error_init(&error); + + if (thread == 0) + thread = _gettid(); + + if (!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.RealtimeKit1", + "MakeThreadHighPriority"))) { + ret = -ENOMEM; + goto finish; + } + + u64 = (dbus_uint64_t) thread; + s32 = (dbus_int32_t) nice_level; + + if (!dbus_message_append_args( + m, + DBUS_TYPE_UINT64, &u64, + DBUS_TYPE_INT32, &s32, + DBUS_TYPE_INVALID)) { + ret = -ENOMEM; + goto finish; + } + + + + if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { + ret = translate_error(error.name); + goto finish; + } + + + if (dbus_set_error_from_message(&error, r)) { + ret = translate_error(error.name); + goto finish; + } + + ret = 0; + +finish: + + if (m) + dbus_message_unref(m); + + if (r) + dbus_message_unref(r); + + dbus_error_free(&error); + + return ret; +} + +#else + +int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) { + return -ENOTSUP; +} + +int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) { + return -ENOTSUP; +} + +#endif diff --git a/src/pulsecore/rtkit.h b/src/pulsecore/rtkit.h new file mode 100644 index 00000000..2081b4e9 --- /dev/null +++ b/src/pulsecore/rtkit.h @@ -0,0 +1,62 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +#ifndef foortkithfoo +#define foortkithfoo + +/*** + Copyright 2009 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the reference implementation for a client for + * RealtimeKit. You don't have to use this, but if do, just copy these + * sources into your repository */ + +#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" +#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" + +/* This is mostly equivalent to sched_setparam(thread, SCHED_RR, { + * .sched_priority = priority }). 'thread' needs to be a kernel thread + * id as returned by gettid(), not a pthread_t! If 'thread' is 0 the + * current thread is used. The returned value is a negative errno + * style error code, or 0 on success. */ +int rtkit_make_realtime(DBusConnection *system_bus, pid_t thread, int priority); + +/* This is mostly equivalent to setpriority(PRIO_PROCESS, thread, + * nice_level). 'thread' needs to be a kernel thread id as returned by + * gettid(), not a pthread_t! If 'thread' is 0 the current thread is + * used. The returned value is a negative errno style error code, or 0 + * on success.*/ +int rtkit_make_high_priority(DBusConnection *system_bus, pid_t thread, int nice_level); + +#ifdef __cplusplus +} +#endif + +#endif -- cgit From bacc5ca6f48f280c781af508250a25bb2012327f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Jun 2009 04:45:19 +0200 Subject: core: use rtkit to acquire high-priority scheduling --- src/pulsecore/core-util.c | 150 ++++++++++++++-------------------------------- src/pulsecore/core-util.h | 3 - 2 files changed, 46 insertions(+), 107 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 1fdd1890..4550344f 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -617,40 +617,20 @@ static int set_scheduler(int rtprio) { int pa_make_realtime(int rtprio) { #ifdef _POSIX_PRIORITY_SCHEDULING - int r, policy; - struct sched_param sp; - int rtprio_try; - - pa_zero(sp); - policy = 0; - - if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { - pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r)); - return -1; - } - -#ifdef SCHED_RESET_ON_FORK - policy &= ~SCHED_RESET_ON_FORK; -#endif - - if ((policy == SCHED_FIFO || policy == SCHED_RR) && sp.sched_priority >= rtprio) { - pa_log_info("Thread already being scheduled with SCHED_FIFO/SCHED_RR with priority %i.", sp.sched_priority); - return 0; - } + int p; if (set_scheduler(rtprio) >= 0) { pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio); return 0; } - for (rtprio_try = rtprio-1; rtprio_try >= 1; rtprio_try--) { - if (set_scheduler(rtprio_try)) { - pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", rtprio_try, rtprio); + for (p = rtprio-1; p >= 1; p--) + if (set_scheduler(p)) { + pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio); return 0; } - } - pa_log_warn("Failed to acquire real-time scheduling: %s", pa_cstrerror(r)); + pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno)); return -1; #else @@ -659,80 +639,42 @@ int pa_make_realtime(int rtprio) { #endif } -/* This is merely used for giving the user a hint. This is not correct - * for anything security related */ -pa_bool_t pa_can_realtime(void) { - - if (geteuid() == 0) - return TRUE; - -#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO) - { - struct rlimit rl; +static int set_nice(int nice_level) { +#ifdef HAVE_DBUS + DBusError error; + DBusConnection *bus; + int r; - if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0) - if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY) - return TRUE; - } + dbus_error_init(&error); #endif -#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE) - { - cap_t cap; - - if ((cap = cap_get_proc())) { - cap_flag_value_t flag = CAP_CLEAR; - - if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0) - if (flag == CAP_SET) { - cap_free(cap); - return TRUE; - } - - cap_free(cap); - } + if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) { + pa_log_debug("setpriority() worked."); + return 0; } -#endif - - return FALSE; -} - -/* This is merely used for giving the user a hint. This is not correct - * for anything security related */ -pa_bool_t pa_can_high_priority(void) { - if (geteuid() == 0) - return TRUE; - -#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO) - { - struct rlimit rl; +#ifdef HAVE_DBUS + /* Try to talk to RealtimeKit */ - if (getrlimit(RLIMIT_NICE, &rl) >= 0) - if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY) - return TRUE; + if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { + pa_log("Failed to connect to system bus: %s\n", error.message); + dbus_error_free(&error); + errno = -EIO; + return -1; } -#endif -#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE) - { - cap_t cap; - - if ((cap = cap_get_proc())) { - cap_flag_value_t flag = CAP_CLEAR; - - if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0) - if (flag == CAP_SET) { - cap_free(cap); - return TRUE; - } + r = rtkit_make_high_priority(bus, 0, nice_level); + dbus_connection_unref(bus); - cap_free(cap); - } + if (r >= 0) { + pa_log_debug("RealtimeKit worked."); + return 0; } + + errno = -r; #endif - return FALSE; + return -1; } /* Raise the priority of the current process as much as possible that @@ -740,22 +682,21 @@ pa_bool_t pa_can_high_priority(void) { int pa_raise_priority(int nice_level) { #ifdef HAVE_SYS_RESOURCE_H - if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) { - int n; + int n; - for (n = nice_level+1; n < 0; n++) { + if (set_nice(nice_level) >= 0) { + pa_log_info("Successfully gained nice level %i.", nice_level); + return 0; + } - if (setpriority(PRIO_PROCESS, 0, n) == 0) { - pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level); - return 0; - } + for (n = nice_level+1; n < 0; n++) + if (set_nice(n) > 0) { + pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level); + return 0; } - pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); - return -1; - } - - pa_log_info("Successfully gained nice level %i.", nice_level); + pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno)); + return -1; #endif #ifdef OS_IS_WIN32 @@ -763,9 +704,10 @@ int pa_raise_priority(int nice_level) { if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) { pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); errno = EPERM; - return .-1; - } else - pa_log_info("Successfully gained high priority class."); + return -1; + } + + pa_log_info("Successfully gained high priority class."); } #endif @@ -780,8 +722,8 @@ void pa_reset_priority(void) { setpriority(PRIO_PROCESS, 0, 0); - memset(&sp, 0, sizeof(sp)); - pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp) == 0); + pa_zero(sp); + pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp); #endif #ifdef OS_IS_WIN32 diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index b841edbb..96a0480a 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -80,9 +80,6 @@ int pa_make_realtime(int rtprio); int pa_raise_priority(int nice_level); void pa_reset_priority(void); -pa_bool_t pa_can_realtime(void); -pa_bool_t pa_can_high_priority(void); - int pa_parse_boolean(const char *s) PA_GCC_PURE; static inline const char *pa_yes_no(pa_bool_t b) { -- cgit From 5dcdd5e3583f32c8bffb5a1892e318747070f5d8 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Sat, 4 Apr 2009 22:56:38 +0300 Subject: perl -p -i -e 's/pa_rtclock_usec/pa_rtclock_now/g' `find . -name '*.[ch]'` --- src/pulsecore/log.c | 2 +- src/pulsecore/ratelimit.c | 2 +- src/pulsecore/rtclock.c | 2 +- src/pulsecore/rtclock.h | 2 +- src/pulsecore/rtpoll.c | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 15d192d6..acff981b 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -294,7 +294,7 @@ void pa_log_levelv_meta( static pa_usec_t start, last; pa_usec_t u, a, r; - u = pa_rtclock_usec(); + u = pa_rtclock_now(); PA_ONCE_BEGIN { start = u; diff --git a/src/pulsecore/ratelimit.c b/src/pulsecore/ratelimit.c index e913ca19..f00587af 100644 --- a/src/pulsecore/ratelimit.c +++ b/src/pulsecore/ratelimit.c @@ -38,7 +38,7 @@ pa_bool_t pa_ratelimit_test(pa_ratelimit *r) { pa_usec_t now; pa_mutex *m; - now = pa_rtclock_usec(); + now = pa_rtclock_now(); m = pa_static_mutex_get(&mutex, FALSE, FALSE); pa_mutex_lock(m); diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c index 65c826a6..53c0258c 100644 --- a/src/pulsecore/rtclock.c +++ b/src/pulsecore/rtclock.c @@ -122,7 +122,7 @@ void pa_rtclock_hrtimer_enable(void) { #endif } -pa_usec_t pa_rtclock_usec(void) { +pa_usec_t pa_rtclock_now(void) { struct timeval tv; return pa_timeval_load(pa_rtclock_get(&tv)); diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h index 03cc1c72..b8a588c0 100644 --- a/src/pulsecore/rtclock.h +++ b/src/pulsecore/rtclock.h @@ -31,7 +31,7 @@ struct timeval; struct timeval *pa_rtclock_get(struct timeval *ts); -pa_usec_t pa_rtclock_usec(void); +pa_usec_t pa_rtclock_now(void); pa_usec_t pa_rtclock_age(const struct timeval *tv); pa_bool_t pa_rtclock_hrtimer(void); diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c index aa8ca321..006b93f6 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -160,7 +160,7 @@ pa_rtpoll *pa_rtpoll_new(void) { PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items); #ifdef DEBUG_TIMING - p->timestamp = pa_rtclock_usec(); + p->timestamp = pa_rtclock_now(); p->slept = p->awake = 0; #endif @@ -394,7 +394,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { #ifdef DEBUG_TIMING { - pa_usec_t now = pa_rtclock_usec(); + pa_usec_t now = pa_rtclock_now(); p->awake = now - p->timestamp; p->timestamp = now; } @@ -421,7 +421,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { #ifdef DEBUG_TIMING { - pa_usec_t now = pa_rtclock_usec(); + pa_usec_t now = pa_rtclock_now(); p->slept = now - p->timestamp; p->timestamp = now; -- cgit From 32e2cd6d3216f780c4cffed0f8eb3c30f2c8d732 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Jun 2009 21:00:06 +0200 Subject: core: get rid of rt sig/timer handling since modern Linux' ppooll() is finally fixed for granularity --- src/pulsecore/rtpoll.c | 176 ++----------------------------------------------- src/pulsecore/rtpoll.h | 3 - src/pulsecore/rtsig.c | 131 ------------------------------------ src/pulsecore/rtsig.h | 39 ----------- 4 files changed, 4 insertions(+), 345 deletions(-) delete mode 100644 src/pulsecore/rtsig.c delete mode 100644 src/pulsecore/rtsig.h (limited to 'src/pulsecore') diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c index aa8ca321..185b8211 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -30,10 +30,6 @@ #include #include -#ifdef __linux__ -#include -#endif - #ifdef HAVE_POLL_H #include #else @@ -47,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -66,20 +61,9 @@ struct pa_rtpoll { 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; -#endif - #ifdef DEBUG_TIMING pa_usec_t timestamp; pa_usec_t slept, awake; @@ -107,52 +91,20 @@ struct pa_rtpoll_item { PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree); -static void signal_handler_noop(int s) { /* write(2, "signal\n", 7); */ } - pa_rtpoll *pa_rtpoll_new(void) { pa_rtpoll *p; p = pa_xnew(pa_rtpoll, 1); -#ifdef HAVE_PPOLL - -#ifdef __linux__ - /* ppoll is broken on Linux < 2.6.16 */ - p->dont_use_ppoll = FALSE; - - { - struct utsname u; - unsigned major, minor, micro; - - pa_assert_se(uname(&u) == 0); - - if (sscanf(u.release, "%u.%u.%u", &major, &minor, µ) != 3 || - (major < 2) || - (major == 2 && minor < 6) || - (major == 2 && minor == 6 && micro < 16)) - - p->dont_use_ppoll = TRUE; - } - -#endif - - p->rtsig = -1; - sigemptyset(&p->sigset_unblocked); - p->timer = (timer_t) -1; - p->timer_armed = FALSE; - -#endif - p->n_pollfd_alloc = 32; p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc); p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc); p->n_pollfd_used = 0; - memset(&p->next_elapse, 0, sizeof(p->next_elapse)); + pa_zero(p->next_elapse); p->timer_enabled = FALSE; p->running = FALSE; - p->installed = FALSE; p->scan_for_dead = FALSE; p->rebuild_needed = FALSE; p->quit = FALSE; @@ -167,46 +119,6 @@ pa_rtpoll *pa_rtpoll_new(void) { return p; } -void pa_rtpoll_install(pa_rtpoll *p) { - pa_assert(p); - pa_assert(!p->installed); - - p->installed = TRUE; - -#ifdef HAVE_PPOLL -# ifdef __linux__ - if (p->dont_use_ppoll) - return; -# endif - - if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) { - pa_log_warn("Failed to reserve POSIX realtime signal."); - return; - } - - pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig)); - - { - sigset_t ss; - struct sigaction sa; - - pa_assert_se(sigemptyset(&ss) == 0); - pa_assert_se(sigaddset(&ss, p->rtsig) == 0); - pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0); - pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0); - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = signal_handler_noop; - pa_assert_se(sigemptyset(&sa.sa_mask) == 0); - - pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0); - - /* We never reset the signal handler. Why should we? */ - } - -#endif -} - static void rtpoll_rebuild(pa_rtpoll *p) { struct pollfd *e, *t; @@ -250,7 +162,6 @@ static void rtpoll_rebuild(pa_rtpoll *p) { if (ra) p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd)); - } static void rtpoll_item_destroy(pa_rtpoll_item *i) { @@ -279,11 +190,6 @@ void pa_rtpoll_free(pa_rtpoll *p) { pa_xfree(p->pollfd); pa_xfree(p->pollfd2); -#ifdef HAVE_PPOLL - if (p->timer != (timer_t) -1) - timer_delete(p->timer); -#endif - pa_xfree(p); } @@ -321,7 +227,6 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { pa_assert(p); pa_assert(!p->running); - pa_assert(p->installed); p->running = TRUE; @@ -402,22 +307,15 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { /* OK, now let's sleep */ #ifdef HAVE_PPOLL - -#ifdef __linux__ - if (!p->dont_use_ppoll) -#endif { struct timespec ts; ts.tv_sec = timeout.tv_sec; ts.tv_nsec = timeout.tv_usec * 1000; - r = ppoll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? &ts : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked); + r = ppoll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? &ts : NULL, NULL); } -#ifdef __linux__ - else -#endif - -#endif +#else r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1); +#endif #ifdef DEBUG_TIMING { @@ -472,73 +370,11 @@ finish: return r < 0 ? r : !p->quit; } -static void update_timer(pa_rtpoll *p) { - pa_assert(p); - -#ifdef HAVE_PPOLL - -#ifdef __linux__ - if (p->dont_use_ppoll) - return; -#endif - - if (p->timer == (timer_t) -1) { - struct sigevent se; - - memset(&se, 0, sizeof(se)); - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = p->rtsig; - - if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0) - if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) { - pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno)); - p->timer = (timer_t) -1; - } - } - - if (p->timer != (timer_t) -1) { - struct itimerspec its; - struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; - sigset_t ss; - - if (p->timer_armed) { - /* First disarm timer */ - memset(&its, 0, sizeof(its)); - pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0); - - /* Remove a signal that might be waiting in the signal q */ - pa_assert_se(sigemptyset(&ss) == 0); - pa_assert_se(sigaddset(&ss, p->rtsig) == 0); - sigtimedwait(&ss, NULL, &ts); - } - - /* And install the new timer */ - if (p->timer_enabled) { - memset(&its, 0, sizeof(its)); - - its.it_value.tv_sec = p->next_elapse.tv_sec; - its.it_value.tv_nsec = p->next_elapse.tv_usec*1000; - - /* Make sure that 0,0 is not understood as - * "disarming" */ - if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) - its.it_value.tv_nsec = 1; - pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0); - } - - p->timer_armed = p->timer_enabled; - } - -#endif -} - void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) { pa_assert(p); pa_timeval_store(&p->next_elapse, usec); p->timer_enabled = TRUE; - - update_timer(p); } void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) { @@ -550,8 +386,6 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) { pa_rtclock_get(&p->next_elapse); pa_timeval_add(&p->next_elapse, usec); p->timer_enabled = TRUE; - - update_timer(p); } void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) { @@ -559,8 +393,6 @@ void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) { memset(&p->next_elapse, 0, sizeof(p->next_elapse)); p->timer_enabled = FALSE; - - update_timer(p); } pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) { diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h index 08776ef0..d2d69cad 100644 --- a/src/pulsecore/rtpoll.h +++ b/src/pulsecore/rtpoll.h @@ -62,9 +62,6 @@ typedef enum pa_rtpoll_priority { pa_rtpoll *pa_rtpoll_new(void); void pa_rtpoll_free(pa_rtpoll *p); -/* Install the rtpoll in the current thread */ -void pa_rtpoll_install(pa_rtpoll *p); - /* Sleep on the rtpoll until the time event, or any of the fd events * is triggered. If "wait" is 0 we don't sleep but only update the * struct pollfd. Returns negative on error, positive if the loop diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c deleted file mode 100644 index 4cd6aa8f..00000000 --- a/src/pulsecore/rtsig.c +++ /dev/null @@ -1,131 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB - - 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. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include -#include - -#include "rtsig.h" - -#ifdef SIGRTMIN - -static void _free_rtsig(void *p) { - pa_rtsig_put(PA_PTR_TO_INT(p)); -} - -PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two((unsigned) (SIGRTMAX-SIGRTMIN+1)), NULL); -PA_STATIC_TLS_DECLARE(rtsig_tls, _free_rtsig); - -static pa_atomic_t rtsig_current = PA_ATOMIC_INIT(-1); - -static int rtsig_start = -1, rtsig_end = -1; - -int pa_rtsig_get(void) { - void *p; - int sig; - - if ((p = pa_flist_pop(PA_STATIC_FLIST_GET(rtsig_flist)))) - return PA_PTR_TO_INT(p); - - sig = pa_atomic_dec(&rtsig_current); - - pa_assert(sig <= SIGRTMAX); - pa_assert(sig <= rtsig_end); - - if (sig < rtsig_start) { - pa_atomic_inc(&rtsig_current); - return -1; - } - - return sig; -} - -int pa_rtsig_get_for_thread(void) { - int sig; - void *p; - - if ((p = PA_STATIC_TLS_GET(rtsig_tls))) - return PA_PTR_TO_INT(p); - - if ((sig = pa_rtsig_get()) < 0) - return -1; - - PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig)); - return sig; -} - -void pa_rtsig_put(int sig) { - pa_assert(sig >= rtsig_start); - pa_assert(sig <= rtsig_end); - - pa_assert_se(pa_flist_push(PA_STATIC_FLIST_GET(rtsig_flist), PA_INT_TO_PTR(sig)) >= 0); -} - -void pa_rtsig_configure(int start, int end) { - int s; - sigset_t ss; - - pa_assert(pa_atomic_load(&rtsig_current) == -1); - - pa_assert(SIGRTMIN <= start); - pa_assert(start <= end); - pa_assert(end <= SIGRTMAX); - - rtsig_start = start; - rtsig_end = end; - - sigemptyset(&ss); - - for (s = rtsig_start; s <= rtsig_end; s++) - pa_assert_se(sigaddset(&ss, s) == 0); - - pa_assert(pthread_sigmask(SIG_BLOCK, &ss, NULL) == 0); - - /* We allocate starting from the end */ - pa_atomic_store(&rtsig_current, rtsig_end); -} - -#else /* SIGRTMIN */ - -int pa_rtsig_get(void) { - return -1; -} - -int pa_rtsig_get_for_thread(void) { - return -1; -} - -void pa_rtsig_put(int sig) { -} - -void pa_rtsig_configure(int start, int end) { -} - -#endif /* SIGRTMIN */ diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h deleted file mode 100644 index e414122d..00000000 --- a/src/pulsecore/rtsig.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef foopulsertsighfoo -#define foopulsertsighfoo - -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 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 - 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. -***/ - -/* Return the next unused POSIX Realtime signals */ -int pa_rtsig_get(void); - -/* If not called before in the current thread, return the next unused - * rtsig, and install it in a TLS region and give it up automatically - * when the thread shuts down */ -int pa_rtsig_get_for_thread(void); - -/* Give an rtsig back. */ -void pa_rtsig_put(int sig); - -/* Block all RT signals */ -void pa_rtsig_configure(int start, int end); - -#endif -- cgit From 125c52889626b2ac408ecbcc8ea85575f5808e07 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Sat, 4 Apr 2009 23:19:53 +0300 Subject: pulse: move pa_rtclock_now in pulsecommon --- src/pulsecore/core-rtclock.c | 152 +++++++++++++++++++++++++++++++++++++++++ src/pulsecore/core-rtclock.h | 45 ++++++++++++ src/pulsecore/log.c | 3 +- src/pulsecore/ratelimit.c | 3 +- src/pulsecore/rtclock.c | 158 ------------------------------------------- src/pulsecore/rtclock.h | 47 ------------- src/pulsecore/rtpoll.c | 2 +- 7 files changed, 202 insertions(+), 208 deletions(-) create mode 100644 src/pulsecore/core-rtclock.c create mode 100644 src/pulsecore/core-rtclock.h delete mode 100644 src/pulsecore/rtclock.c delete mode 100644 src/pulsecore/rtclock.h (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-rtclock.c b/src/pulsecore/core-rtclock.c new file mode 100644 index 00000000..0610e297 --- /dev/null +++ b/src/pulsecore/core-rtclock.c @@ -0,0 +1,152 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + 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. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + +#include +#include +#include + +#include "core-rtclock.h" + +pa_usec_t pa_rtclock_age(const struct timeval *tv) { + struct timeval now; + pa_assert(tv); + + return pa_timeval_diff(pa_rtclock_get(&now), tv); +} + +struct timeval *pa_rtclock_get(struct timeval *tv) { +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + +#ifdef CLOCK_MONOTONIC + /* No locking or atomic ops for no_monotonic here */ + static pa_bool_t no_monotonic = FALSE; + + if (!no_monotonic) + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) + no_monotonic = TRUE; + + if (no_monotonic) +#endif + pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); + + pa_assert(tv); + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + + return tv; + +#else /* HAVE_CLOCK_GETTIME */ + + return pa_gettimeofday(tv); + +#endif +} + +pa_bool_t pa_rtclock_hrtimer(void) { +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + +#ifdef CLOCK_MONOTONIC + if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0) + return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; +#endif + + pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0); + return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; + +#else /* HAVE_CLOCK_GETTIME */ + + return FALSE; + +#endif +} + +#define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC)) + +void pa_rtclock_hrtimer_enable(void) { +#ifdef PR_SET_TIMERSLACK + int slack_ns; + + if ((slack_ns = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0)) < 0) { + pa_log_info("PR_GET_TIMERSLACK/PR_SET_TIMERSLACK not supported."); + return; + } + + pa_log_debug("Timer slack is set to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC)); + + if (slack_ns > TIMER_SLACK_NS) { + slack_ns = TIMER_SLACK_NS; + + pa_log_debug("Setting timer slack to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC)); + + if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) { + pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno)); + return; + } + } + +#endif +} + +struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) { + +#ifdef HAVE_CLOCK_GETTIME + struct timeval wc_now, rt_now; + + pa_gettimeofday(&wc_now); + pa_rtclock_get(&rt_now); + + pa_assert(tv); + + if (pa_timeval_cmp(&wc_now, tv) < 0) + pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now)); + else + pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv)); + + *tv = rt_now; +#endif + + 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/core-rtclock.h b/src/pulsecore/core-rtclock.h new file mode 100644 index 00000000..83ff7c7c --- /dev/null +++ b/src/pulsecore/core-rtclock.h @@ -0,0 +1,45 @@ +#ifndef foopulsertclockhfoo +#define foopulsertclockhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 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 + 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 +#include + +struct timeval; + +/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC */ + +struct timeval *pa_rtclock_get(struct timeval *ts); + +pa_usec_t pa_rtclock_age(const struct timeval *tv); +pa_bool_t pa_rtclock_hrtimer(void); +void pa_rtclock_hrtimer_enable(void); + +/* timer with a resolution better than this are considered high-resolution */ +#define PA_HRTIMER_THRESHOLD_USEC 10 + +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/log.c b/src/pulsecore/log.c index acff981b..8c21ee6c 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -38,6 +38,7 @@ #include #endif +#include #include #include #include @@ -45,7 +46,7 @@ #include #include -#include +#include #include #include diff --git a/src/pulsecore/ratelimit.c b/src/pulsecore/ratelimit.c index f00587af..844dd77d 100644 --- a/src/pulsecore/ratelimit.c +++ b/src/pulsecore/ratelimit.c @@ -23,7 +23,8 @@ #include #endif -#include +#include + #include #include diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c deleted file mode 100644 index 53c0258c..00000000 --- a/src/pulsecore/rtclock.c +++ /dev/null @@ -1,158 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB - - 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. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_SYS_PRCTL_H -#include -#endif - -#include -#include -#include - -#include "rtclock.h" - -pa_usec_t pa_rtclock_age(const struct timeval *tv) { - struct timeval now; - pa_assert(tv); - - return pa_timeval_diff(pa_rtclock_get(&now), tv); -} - -struct timeval *pa_rtclock_get(struct timeval *tv) { -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; - -#ifdef CLOCK_MONOTONIC - /* No locking or atomic ops for no_monotonic here */ - static pa_bool_t no_monotonic = FALSE; - - if (!no_monotonic) - if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) - no_monotonic = TRUE; - - if (no_monotonic) -#endif - pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); - - pa_assert(tv); - - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / 1000; - - return tv; - -#else /* HAVE_CLOCK_GETTIME */ - - return pa_gettimeofday(tv); - -#endif -} - -pa_bool_t pa_rtclock_hrtimer(void) { -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; - -#ifdef CLOCK_MONOTONIC - if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0) - return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; -#endif - - pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0); - return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; - -#else /* HAVE_CLOCK_GETTIME */ - - return FALSE; - -#endif -} - -#define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC)) - -void pa_rtclock_hrtimer_enable(void) { -#ifdef PR_SET_TIMERSLACK - int slack_ns; - - if ((slack_ns = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0)) < 0) { - pa_log_info("PR_GET_TIMERSLACK/PR_SET_TIMERSLACK not supported."); - return; - } - - pa_log_debug("Timer slack is set to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC)); - - if (slack_ns > TIMER_SLACK_NS) { - slack_ns = TIMER_SLACK_NS; - - pa_log_debug("Setting timer slack to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC)); - - if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) { - pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno)); - return; - } - } - -#endif -} - -pa_usec_t pa_rtclock_now(void) { - struct timeval tv; - - return pa_timeval_load(pa_rtclock_get(&tv)); -} - -struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) { - -#ifdef HAVE_CLOCK_GETTIME - struct timeval wc_now, rt_now; - - pa_gettimeofday(&wc_now); - pa_rtclock_get(&rt_now); - - pa_assert(tv); - - if (pa_timeval_cmp(&wc_now, tv) < 0) - pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now)); - else - pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv)); - - *tv = rt_now; -#endif - - 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 deleted file mode 100644 index b8a588c0..00000000 --- a/src/pulsecore/rtclock.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef foopulsertclockhfoo -#define foopulsertclockhfoo - -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 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 - 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 -#include - -struct timeval; - -/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC */ - -struct timeval *pa_rtclock_get(struct timeval *ts); - -pa_usec_t pa_rtclock_now(void); - -pa_usec_t pa_rtclock_age(const struct timeval *tv); -pa_bool_t pa_rtclock_hrtimer(void); -void pa_rtclock_hrtimer_enable(void); - -/* timer with a resolution better than this are considered high-resolution */ -#define PA_HRTIMER_THRESHOLD_USEC 10 - -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 006b93f6..9401debd 100644 --- a/src/pulsecore/rtpoll.c +++ b/src/pulsecore/rtpoll.c @@ -44,7 +44,7 @@ #include #include -#include +#include #include #include #include -- cgit From 0955e3d45b6e992308e2d51fcbf28a9f9376f788 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Sun, 5 Apr 2009 02:13:43 +0300 Subject: Base mainloop on pa_rtclock_now() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the mainloop to monotonic based time events. Introduces 4 helper functions: pa_{context,core}_rttime_{new,restart}(), that fill correctly a timeval with the rtclock flag set if the mainloop supports it. Both mainloop-test and mainloop-test-glib works with rt and timeval based time events. PulseAudio and clients should be fully functional. This patch has received several iterations, and this one as been largely untested. Signed-off-by: Marc-André Lureau --- src/pulsecore/avahi-wrap.c | 9 ++++--- src/pulsecore/core-rtclock.c | 35 +++++++++++++++++++++++++ src/pulsecore/core-rtclock.h | 5 ++++ src/pulsecore/core-scache.c | 19 +++++--------- src/pulsecore/core.c | 28 +++++++++++++++----- src/pulsecore/core.h | 4 +++ src/pulsecore/dbus-shared.c | 2 +- src/pulsecore/dbus-util.c | 58 +++++++++++++++++++++++++---------------- src/pulsecore/dbus-util.h | 2 +- src/pulsecore/pdispatch.c | 13 ++++----- src/pulsecore/pdispatch.h | 2 +- src/pulsecore/protocol-esound.c | 15 +++++------ src/pulsecore/protocol-native.c | 17 +++++------- src/pulsecore/socket-client.c | 22 ++++++++-------- src/pulsecore/socket-client.h | 2 +- 15 files changed, 149 insertions(+), 84 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c index 56d9d3dd..f1f08bcc 100644 --- a/src/pulsecore/avahi-wrap.c +++ b/src/pulsecore/avahi-wrap.c @@ -23,6 +23,7 @@ #include #endif +#include #include #include @@ -116,14 +117,13 @@ struct AvahiTimeout { void *userdata; }; -static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { - AvahiTimeout *t = userdata; +static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { + AvahiTimeout *to = userdata; pa_assert(a); pa_assert(e); - pa_assert(t); - t->callback(t, t->userdata); + to->callback(to, to->userdata); } static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { @@ -145,6 +145,7 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, } static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { + pa_assert(t); if (t->time_event && tv) diff --git a/src/pulsecore/core-rtclock.c b/src/pulsecore/core-rtclock.c index 0610e297..1fa71c80 100644 --- a/src/pulsecore/core-rtclock.c +++ b/src/pulsecore/core-rtclock.c @@ -150,3 +150,38 @@ pa_usec_t pa_timespec_load(const struct timespec *ts) { (pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC + (pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC; } + + +static struct timeval* wallclock_from_rtclock(struct timeval *tv) { + +#ifdef HAVE_CLOCK_GETTIME + struct timeval wc_now, rt_now; + + pa_gettimeofday(&wc_now); + pa_rtclock_get(&rt_now); + + pa_assert(tv); + + if (pa_timeval_cmp(&rt_now, tv) < 0) + pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now)); + else + pa_timeval_sub(&wc_now, pa_timeval_diff(&rt_now, tv)); + + *tv = wc_now; +#endif + + return tv; +} + +struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock) { + pa_assert(tv); + + pa_timeval_store(tv, v); + + if (rtclock) + tv->tv_usec |= PA_TIMEVAL_RTCLOCK; + else + wallclock_from_rtclock(tv); + + return tv; +} diff --git a/src/pulsecore/core-rtclock.h b/src/pulsecore/core-rtclock.h index 83ff7c7c..3c90068b 100644 --- a/src/pulsecore/core-rtclock.h +++ b/src/pulsecore/core-rtclock.h @@ -38,8 +38,13 @@ void pa_rtclock_hrtimer_enable(void); /* timer with a resolution better than this are considered high-resolution */ #define PA_HRTIMER_THRESHOLD_USEC 10 +/* bit to set in tv.tv_usec to mark that the timeval is in monotonic time */ +#define PA_TIMEVAL_RTCLOCK (1 << 30) + struct timeval* pa_rtclock_from_wallclock(struct timeval *tv); pa_usec_t pa_timespec_load(const struct timespec *ts); +struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock); + #endif diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 086f5fcb..4c5a4b26 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -61,11 +63,10 @@ #include "core-scache.h" -#define UNLOAD_POLL_TIME 60 +#define UNLOAD_POLL_TIME (60 * PA_USEC_PER_SEC) -static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_core *c = userdata; - struct timeval ntv; pa_assert(c); pa_assert(c->mainloop == m); @@ -73,9 +74,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct t pa_scache_unload_unused(c); - pa_gettimeofday(&ntv); - ntv.tv_sec += UNLOAD_POLL_TIME; - m->time_restart(e, &ntv); + pa_core_rttime_restart(c, e, pa_rtclock_now() + UNLOAD_POLL_TIME); } static void free_entry(pa_scache_entry *e) { @@ -256,12 +255,8 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, pa_proplist_sets(e->proplist, PA_PROP_MEDIA_FILENAME, filename); - if (!c->scache_auto_unload_event) { - struct timeval ntv; - pa_gettimeofday(&ntv); - ntv.tv_sec += UNLOAD_POLL_TIME; - c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); - } + if (!c->scache_auto_unload_event) + c->scache_auto_unload_event = pa_core_rttime_new(c, pa_rtclock_now() + UNLOAD_POLL_TIME, timeout_callback, c); if (idx) *idx = e->index; diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 06573f17..f5eb8352 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -214,7 +216,7 @@ static void core_free(pa_object *o) { pa_xfree(c); } -static void exit_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void exit_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_core *c = userdata; pa_assert(c->exit_event == e); @@ -229,11 +231,7 @@ void pa_core_check_idle(pa_core *c) { c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) { - struct timeval tv; - pa_gettimeofday(&tv); - tv.tv_sec+= c->exit_idle_time; - - c->exit_event = c->mainloop->time_new(c->mainloop, &tv, exit_callback, c); + c->exit_event = pa_core_rttime_new(c, pa_rtclock_now() + c->exit_idle_time * PA_USEC_PER_SEC, exit_callback, c); } else if (c->exit_event && pa_idxset_size(c->clients) > 0) { c->mainloop->time_free(c->exit_event); @@ -261,3 +259,21 @@ void pa_core_maybe_vacuum(pa_core *c) { pa_log_debug("Hmm, no streams around, trying to vacuum."); pa_mempool_vacuum(c->mempool); } + +pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) { + struct timeval tv; + + pa_assert(c); + pa_assert(c->mainloop); + + return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, TRUE), cb, userdata); +} + +void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) { + struct timeval tv; + + pa_assert(c); + pa_assert(c->mainloop); + + c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, TRUE)); +} diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 09a880c4..e7abd61b 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -183,4 +183,8 @@ int pa_core_exit(pa_core *c, pa_bool_t force, int retval); void pa_core_maybe_vacuum(pa_core *c); +/* wrapper for c->mainloop->time_*() RT time events */ +pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata); +void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec); + #endif diff --git a/src/pulsecore/dbus-shared.c b/src/pulsecore/dbus-shared.c index 9d9445b6..20ef9b1e 100644 --- a/src/pulsecore/dbus-shared.c +++ b/src/pulsecore/dbus-shared.c @@ -70,7 +70,7 @@ pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *err if ((pconn = pa_shared_get(c, prop_name[type]))) return pa_dbus_connection_ref(pconn); - if (!(conn = pa_dbus_wrap_connection_new(c->mainloop, type, error))) + if (!(conn = pa_dbus_wrap_connection_new(c->mainloop, TRUE, type, error))) return NULL; return dbus_connection_new(c, conn, prop_name[type]); diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c index ece36def..4e6148f0 100644 --- a/src/pulsecore/dbus-util.c +++ b/src/pulsecore/dbus-util.c @@ -26,9 +26,11 @@ #include -#include +#include #include +#include +#include #include #include @@ -38,6 +40,12 @@ struct pa_dbus_wrap_connection { pa_mainloop_api *mainloop; DBusConnection *connection; pa_defer_event* dispatch_event; + pa_bool_t use_rtclock:1; +}; + +struct timeout_data { + pa_dbus_wrap_connection *c; + DBusTimeout *timeout; }; static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) { @@ -118,16 +126,18 @@ static void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_e } /* pa_time_event_cb_t timer event handler */ -static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *tv, void *userdata) { - DBusTimeout *timeout = userdata; +static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *t, void *userdata) { + struct timeval tv; + struct timeout_data *d = userdata; - if (dbus_timeout_get_enabled(timeout)) { - struct timeval next = *tv; - dbus_timeout_handle(timeout); + pa_assert(d); + pa_assert(d->c); + + if (dbus_timeout_get_enabled(d->timeout)) { + dbus_timeout_handle(d->timeout); /* restart it for the next scheduled time */ - pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - ea->time_restart(e, &next); + ea->time_restart(e, pa_timeval_rtstore(&tv, pa_timeval_load(t) + dbus_timeout_get_interval(d->timeout) * PA_USEC_PER_MSEC, d->c->use_rtclock)); } } @@ -179,11 +189,16 @@ static void toggle_watch(DBusWatch *watch, void *data) { c->mainloop->io_enable(ev, get_watch_flags(watch)); } +static void time_event_destroy_cb(pa_mainloop_api *a, pa_time_event *e, void *userdata) { + pa_xfree(userdata); +} + /* DBusAddTimeoutFunction callback for pa mainloop */ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { pa_dbus_wrap_connection *c = data; pa_time_event *ev; struct timeval tv; + struct timeout_data *d; pa_assert(timeout); pa_assert(c); @@ -191,10 +206,11 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { if (!dbus_timeout_get_enabled(timeout)) return FALSE; - pa_gettimeofday(&tv); - pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - - ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout); + d = pa_xnew(struct timeout_data, 1); + d->c = c; + d->timeout = timeout; + ev = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + dbus_timeout_get_interval(timeout) * PA_USEC_PER_MSEC, c->use_rtclock), handle_time_event, d); + c->mainloop->time_set_destroy(ev, time_event_destroy_cb); dbus_timeout_set_data(timeout, ev, NULL); @@ -215,23 +231,20 @@ static void remove_timeout(DBusTimeout *timeout, void *data) { /* DBusTimeoutToggledFunction callback for pa mainloop */ static void toggle_timeout(DBusTimeout *timeout, void *data) { - pa_dbus_wrap_connection *c = data; + struct timeout_data *d = data; pa_time_event *ev; + struct timeval tv; + pa_assert(d); + pa_assert(d->c); pa_assert(timeout); - pa_assert(c); pa_assert_se(ev = dbus_timeout_get_data(timeout)); if (dbus_timeout_get_enabled(timeout)) { - struct timeval tv; - - pa_gettimeofday(&tv); - pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - - c->mainloop->time_restart(ev, &tv); + d->c->mainloop->time_restart(ev, pa_timeval_rtstore(&tv, pa_rtclock_now() + dbus_timeout_get_interval(timeout) * PA_USEC_PER_MSEC, d->c->use_rtclock)); } else - c->mainloop->time_restart(ev, NULL); + d->c->mainloop->time_restart(ev, pa_timeval_rtstore(&tv, PA_USEC_INVALID, d->c->use_rtclock)); } static void wakeup_main(void *userdata) { @@ -244,7 +257,7 @@ static void wakeup_main(void *userdata) { c->mainloop->defer_enable(c->dispatch_event, 1); } -pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBusType type, DBusError *error) { +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, pa_bool_t use_rtclock, DBusBusType type, DBusError *error) { DBusConnection *conn; pa_dbus_wrap_connection *pconn; char *id; @@ -257,6 +270,7 @@ pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBus pconn = pa_xnew(pa_dbus_wrap_connection, 1); pconn->mainloop = m; pconn->connection = conn; + pconn->use_rtclock = use_rtclock; dbus_connection_set_exit_on_disconnect(conn, FALSE); dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); diff --git a/src/pulsecore/dbus-util.h b/src/pulsecore/dbus-util.h index 55cda7a0..9ff298d8 100644 --- a/src/pulsecore/dbus-util.h +++ b/src/pulsecore/dbus-util.h @@ -30,7 +30,7 @@ /* A wrap connection is not shared or refcounted, it is available in client side */ typedef struct pa_dbus_wrap_connection pa_dbus_wrap_connection; -pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, DBusBusType type, DBusError *error); +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, pa_bool_t use_rtclock, DBusBusType type, DBusError *error); void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* conn); DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *conn); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 4388831a..fc8ce76f 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ #include #include #include +#include #include "pdispatch.h" @@ -204,6 +206,7 @@ struct pa_pdispatch { pa_pdispatch_drain_callback drain_callback; void *drain_userdata; const pa_creds *creds; + pa_bool_t use_rtclock:1; }; static void reply_info_free(struct reply_info *r) { @@ -220,7 +223,7 @@ static void reply_info_free(struct reply_info *r) { pa_xfree(r); } -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_t*table, unsigned entries) { +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, pa_bool_t use_rtclock, const pa_pdispatch_cb_t *table, unsigned entries) { pa_pdispatch *pd; pa_assert(mainloop); @@ -235,6 +238,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ pd->drain_callback = NULL; pd->drain_userdata = NULL; pd->creds = NULL; + pd->use_rtclock = use_rtclock; return pd; } @@ -342,7 +346,7 @@ finish: return ret; } -static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, const struct timeval *t, void *userdata) { struct reply_info*r = userdata; pa_assert(r); @@ -371,10 +375,7 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa r->free_cb = free_cb; r->tag = tag; - pa_gettimeofday(&tv); - tv.tv_sec += timeout; - - pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r)); + pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + timeout * PA_USEC_PER_SEC, pd->use_rtclock), timeout_callback, r)); PA_LLIST_PREPEND(struct reply_info, pd->replies, r); } diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 5c31d80e..dae475af 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -37,7 +37,7 @@ typedef struct pa_pdispatch pa_pdispatch; typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); typedef void (*pa_pdispatch_drain_callback)(pa_pdispatch *pd, void *userdata); -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table, unsigned entries); +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, pa_bool_t use_rtclock, const pa_pdispatch_cb_t*table, unsigned entries); void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index ad7cd045..f64552aa 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,7 @@ #define MAX_CONNECTIONS 64 /* Kick a client if it doesn't authenticate within this time */ -#define AUTH_TIMEOUT 5 +#define AUTH_TIMEOUT (5*PA_USEC_PER_SEC) #define DEFAULT_COOKIE_FILE ".esd_auth" @@ -1459,11 +1460,10 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { /*** entry points ***/ -static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auth_timeout(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { connection *c = CONNECTION(userdata); pa_assert(m); - pa_assert(tv); connection_assert_ref(c); pa_assert(c->auth_timeout_event == e); @@ -1553,12 +1553,9 @@ void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esou c->authorized = TRUE; } - if (!c->authorized) { - struct timeval tv; - pa_gettimeofday(&tv); - tv.tv_sec += AUTH_TIMEOUT; - c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); - } else + if (!c->authorized) + c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c); + else c->auth_timeout_event = NULL; c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 48f7b135..cda7ef57 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -61,7 +62,7 @@ #include "protocol-native.h" /* Kick a client if it doesn't authenticate within this time */ -#define AUTH_TIMEOUT 60 +#define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC) /* Don't accept more connection than this */ #define MAX_CONNECTIONS 64 @@ -4479,11 +4480,10 @@ static void client_send_event_cb(pa_client *client, const char*event, pa_proplis /*** module entry points ***/ -static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); pa_assert(m); - pa_assert(tv); pa_native_connection_assert_ref(c); pa_assert(c->auth_timeout_event == e); @@ -4541,12 +4541,9 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati c->authorized = TRUE; } - if (!c->authorized) { - struct timeval tv; - pa_gettimeofday(&tv); - tv.tv_sec += AUTH_TIMEOUT; - c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); - } else + if (!c->authorized) + c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c); + else c->auth_timeout_event = NULL; c->is_local = pa_iochannel_socket_is_local(io); @@ -4565,7 +4562,7 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c); pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c); - c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); + c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX); c->record_streams = pa_idxset_new(NULL, NULL); c->output_streams = pa_idxset_new(NULL, NULL); diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index dc23bff6..24535157 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -52,12 +52,14 @@ #include #endif +#include #include #include #include #include #include +#include #include #include #include @@ -420,12 +422,11 @@ fail: #endif -static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_socket_client *c = userdata; pa_assert(m); pa_assert(e); - pa_assert(tv); pa_assert(c); if (c->fd >= 0) { @@ -437,17 +438,16 @@ static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeva do_call(c); } -static void start_timeout(pa_socket_client *c) { +static void start_timeout(pa_socket_client *c, pa_bool_t use_rtclock) { struct timeval tv; + pa_assert(c); pa_assert(!c->timeout_event); - pa_gettimeofday(&tv); - pa_timeval_add(&tv, CONNECT_TIMEOUT * PA_USEC_PER_SEC); - c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); + c->timeout_event = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + CONNECT_TIMEOUT * PA_USEC_PER_SEC, use_rtclock), timeout_cb, c); } -pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*name, uint16_t default_port) { +pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char*name, uint16_t default_port) { pa_socket_client *c = NULL; pa_parsed_address a; @@ -463,7 +463,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam switch (a.type) { case PA_PARSED_ADDRESS_UNIX: if ((c = pa_socket_client_new_unix(m, a.path_or_host))) - start_timeout(c); + start_timeout(c, use_rtclock); break; case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ @@ -499,7 +499,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c); c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints); pa_assert(c->asyncns_query); - start_timeout(c); + start_timeout(c, use_rtclock); } #elif defined(HAVE_GETADDRINFO) { @@ -513,7 +513,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam if (res->ai_addr) { if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) - start_timeout(c); + start_timeout(c, use_rtclock); } freeaddrinfo(res); @@ -546,7 +546,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam s.sin_port = htons(a.port); if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s)))) - start_timeout(c); + start_timeout(c, use_rtclock); } #endif /* HAVE_LIBASYNCNS */ } diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h index ed36400c..b896afa9 100644 --- a/src/pulsecore/socket-client.h +++ b/src/pulsecore/socket-client.h @@ -40,7 +40,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[ #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); +pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char *a, uint16_t default_port); pa_socket_client* pa_socket_client_ref(pa_socket_client *c); void pa_socket_client_unref(pa_socket_client *c); -- cgit From e4d914c945c13d23b131d7ba75fbdd03cb6d0043 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Sat, 20 Jun 2009 16:52:41 +0300 Subject: rtclock: fix issues found by Lennart --- src/pulsecore/core-rtclock.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-rtclock.c b/src/pulsecore/core-rtclock.c index 1fa71c80..a4a70bee 100644 --- a/src/pulsecore/core-rtclock.c +++ b/src/pulsecore/core-rtclock.c @@ -176,6 +176,9 @@ static struct timeval* wallclock_from_rtclock(struct timeval *tv) { struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock) { pa_assert(tv); + if (v == PA_USEC_INVALID) + return NULL; + pa_timeval_store(tv, v); if (rtclock) -- cgit From 882cdfc123d89a393d237e130a6f8e213c91dc40 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Jun 2009 00:17:26 +0200 Subject: rtclock: fix type of PA_TIMEVAL_RTCLOCK --- src/pulsecore/core-rtclock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-rtclock.h b/src/pulsecore/core-rtclock.h index 3c90068b..9f5ae2dd 100644 --- a/src/pulsecore/core-rtclock.h +++ b/src/pulsecore/core-rtclock.h @@ -39,7 +39,7 @@ void pa_rtclock_hrtimer_enable(void); #define PA_HRTIMER_THRESHOLD_USEC 10 /* bit to set in tv.tv_usec to mark that the timeval is in monotonic time */ -#define PA_TIMEVAL_RTCLOCK (1 << 30) +#define PA_TIMEVAL_RTCLOCK ((time_t) (1LU << 30)) struct timeval* pa_rtclock_from_wallclock(struct timeval *tv); -- cgit From d965000982060bc1c92555897828808ff5d928f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Jun 2009 03:55:32 +0200 Subject: rtclock: make use of constants when converting between nsec and usec --- src/pulsecore/core-rtclock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/core-rtclock.c b/src/pulsecore/core-rtclock.c index a4a70bee..3b3e3a64 100644 --- a/src/pulsecore/core-rtclock.c +++ b/src/pulsecore/core-rtclock.c @@ -65,7 +65,7 @@ struct timeval *pa_rtclock_get(struct timeval *tv) { pa_assert(tv); tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / 1000; + tv->tv_usec = ts.tv_nsec / PA_NSEC_PER_USEC; return tv; @@ -82,11 +82,11 @@ pa_bool_t pa_rtclock_hrtimer(void) { #ifdef CLOCK_MONOTONIC if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0) - return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; + return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC); #endif pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0); - return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; + return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC); #else /* HAVE_CLOCK_GETTIME */ -- cgit From 2654eb7781ddcfe53064745bbad77bffe5c8eada Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Jun 2009 18:54:17 +0200 Subject: sndfile: fix build on BE archs --- src/pulsecore/sndfile-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sndfile-util.c b/src/pulsecore/sndfile-util.c index 032aefca..4f7f8bdb 100644 --- a/src/pulsecore/sndfile-util.c +++ b/src/pulsecore/sndfile-util.c @@ -113,7 +113,7 @@ int pa_sndfile_write_sample_spec(SF_INFO *sfi, pa_sample_spec *ss) { break; case PA_SAMPLE_S32LE: - case PA_SAMPLE_S32RE: + case PA_SAMPLE_S32BE: ss->format = PA_SAMPLE_S32NE; sfi->format |= SF_FORMAT_PCM_32; break; -- cgit