summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map-file1
-rw-r--r--src/pulse/context.c17
-rw-r--r--src/pulse/context.h22
-rw-r--r--src/pulse/def.h10
-rw-r--r--src/pulse/stream.c10
-rw-r--r--src/pulse/stream.h17
-rw-r--r--src/pulsecore/memblock.c2
-rw-r--r--src/pulsecore/protocol-native.c29
-rw-r--r--src/pulsecore/svolume_mmx.c4
-rw-r--r--src/pulsecore/svolume_sse.c10
-rw-r--r--src/pulsecore/time-smoother.c7
-rw-r--r--src/utils/pactl.c22
-rw-r--r--src/utils/pasuspender.c2
13 files changed, 131 insertions, 22 deletions
diff --git a/src/map-file b/src/map-file
index 6f7bdace..50111224 100644
--- a/src/map-file
+++ b/src/map-file
@@ -66,6 +66,7 @@ pa_context_get_source_info_list;
pa_context_get_source_output_info;
pa_context_get_source_output_info_list;
pa_context_get_state;
+pa_context_get_tile_size;
pa_context_is_local;
pa_context_is_pending;
pa_context_kill_client;
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 7468d0a9..e33143d9 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -1488,6 +1488,7 @@ pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_even
struct timeval tv;
pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
pa_assert(c->mainloop);
if (usec == PA_USEC_INVALID)
@@ -1502,8 +1503,10 @@ void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec)
struct timeval tv;
pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
pa_assert(c->mainloop);
+
if (usec == PA_USEC_INVALID)
c->mainloop->time_restart(e, NULL);
else {
@@ -1511,3 +1514,17 @@ void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec)
c->mainloop->time_restart(e, &tv);
}
}
+
+size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss) {
+ size_t fs, mbs;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
+ PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
+
+ fs = ss ? pa_frame_size(ss) : 1;
+ mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c->mempool), fs);
+ return PA_MAX(mbs, fs);
+}
diff --git a/src/pulse/context.h b/src/pulse/context.h
index ecff58df..6ac8ee56 100644
--- a/src/pulse/context.h
+++ b/src/pulse/context.h
@@ -255,12 +255,28 @@ pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[]
uint32_t pa_context_get_index(pa_context *s);
/** Create a new timer event source for the specified time (wrapper
- for mainloop->time_new). \since 0.9.16 */
+ * for mainloop->time_new). \since 0.9.16 */
pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata);
-/** Restart a running or expired timer event source (wrapper
- for mainloop->time_restart). \since 0.9.16 */
+
+/** Restart a running or expired timer event source (wrapper for
+ * mainloop->time_restart). \since 0.9.16 */
void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec);
+/* Return the optimal block size for passing around audio buffers. It
+ * is recommended to allocate buffers of the size returned here when
+ * writing audio data to playback streams, if the latency constraints
+ * permit this. It is not recommended writing larger blocks than this
+ * because usually they will then be split up internally into chunks
+ * of this size. It is not recommended writing smaller blocks than
+ * this (unless required due to latency demands) because this
+ * increases CPU usage. If ss is NULL you will be returned the
+ * byte-exact tile size. If you pass a valid ss, then the tile size
+ * will be rounded down to multiple of the frame size. This is
+ * supposed to be used in a construct such as
+ * pa_context_get_tile_size(pa_stream_get_context(s),
+ * pa_stream_get_sample_spec(ss)); \since 0.9.20 */
+size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss);
+
PA_C_DECL_END
#endif
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 5d0a0b4b..30a076d5 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -276,11 +276,18 @@ typedef enum pa_stream_flags {
* whether to create the stream in muted or in unmuted
* state. \since 0.9.15 */
- PA_STREAM_FAIL_ON_SUSPEND = 0x20000U
+ PA_STREAM_FAIL_ON_SUSPEND = 0x20000U,
/**< If the sink/source this stream is connected to is suspended
* during the creation of this stream, cause it to fail. If the
* sink/source is being suspended during creation of this stream,
* make sure this stream is terminated. \since 0.9.15 */
+
+ PA_STREAM_RELATIVE_VOLUME = 0x40000U,
+ /**< If a volume is passed when this stream is created, consider
+ * it relative to the sink's current volume, never as absolute
+ * device volume. If this is not specified the volume will be
+ * consider absolute when the sink is in flat volume mode,
+ * relative otherwise. \since 0.9.20 */
} pa_stream_flags_t;
/** \cond fulldocs */
@@ -307,6 +314,7 @@ typedef enum pa_stream_flags {
#define PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
#define PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
#define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
+#define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
/** \endcond */
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 2bc2b1e4..29979625 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1025,7 +1025,8 @@ static int create_stream(
PA_STREAM_EARLY_REQUESTS|
PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|
PA_STREAM_START_UNMUTED|
- PA_STREAM_FAIL_ON_SUSPEND)), PA_ERR_INVALID);
+ PA_STREAM_FAIL_ON_SUSPEND|
+ PA_STREAM_RELATIVE_VOLUME)), PA_ERR_INVALID);
PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
@@ -1158,6 +1159,13 @@ static int create_stream(
pa_tagstruct_put_boolean(t, flags & PA_STREAM_FAIL_ON_SUSPEND);
}
+ if (s->context->version >= 17) {
+
+ if (s->direction == PA_STREAM_PLAYBACK)
+ pa_tagstruct_put_boolean(t, flags & PA_STREAM_RELATIVE_VOLUME);
+
+ }
+
pa_pstream_send_tagstruct(s->context->pstream, t);
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 2e8e71a0..bc54a118 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -401,7 +401,22 @@ int pa_stream_is_suspended(pa_stream *s);
* not, and negative on error. \since 0.9.11 */
int pa_stream_is_corked(pa_stream *s);
-/** Connect the stream to a sink */
+/** Connect the stream to a sink. It is strongly recommended to pass
+ * NULL in both dev and volume and not to set either
+ * PA_STREAM_START_MUTED nor PA_STREAM_START_UNMUTED -- unless these
+ * options are directly dependant on user input or configuration. If
+ * you follow this rule then the sound server will have the full
+ * flexibility to choose the device, volume and mute status
+ * automatically, based on server-side policies, heuristics and stored
+ * information from previous uses. Also the server may choose to
+ * reconfigure audio devices to make other sinks/sources or
+ * capabilities available to be able to accept the stream. Before
+ * 0.9.20 it was not defined whether the 'volume' parameter was
+ * interpreted relative to the sink's current volume or treated as
+ * absolute device volume. Since 0.9.20 it is an absolute volume when
+ * the sink is in flat volume mode, and relative otherwise, thus
+ * making sure the volume passed here has always the same semantics as
+ * the volume passed to pa_context_set_sink_input_volume(). */
int pa_stream_connect_playback(
pa_stream *s /**< The stream to connect to a sink */,
const char *dev /**< Name of the sink to connect to, or NULL for default */ ,
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index eac4a59b..f38b17c6 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -54,7 +54,7 @@
* stored in SHM and our OS does not commit the memory before we use
* it for the first time. */
#define PA_MEMPOOL_SLOTS_MAX 1024
-#define PA_MEMPOOL_SLOT_SIZE (128*1024)
+#define PA_MEMPOOL_SLOT_SIZE (64*1024)
#define PA_MEMEXPORT_SLOTS_MAX 128
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index d06dd4eb..bb29a196 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1002,6 +1002,7 @@ static playback_stream* playback_stream_new(
pa_proplist *p,
pa_bool_t adjust_latency,
pa_bool_t early_requests,
+ pa_bool_t relative_volume,
int *ret) {
playback_stream *s, *ssync;
@@ -1044,13 +1045,21 @@ static playback_stream* playback_stream_new(
data.driver = __FILE__;
data.module = c->options->module;
data.client = c->client;
- data.sink = sink;
+ if (sink) {
+ data.sink = sink;
+ data.save_sink = TRUE;
+ }
pa_sink_input_new_data_set_sample_spec(&data, ss);
pa_sink_input_new_data_set_channel_map(&data, map);
- if (volume)
+ if (volume) {
pa_sink_input_new_data_set_volume(&data, volume);
- if (muted_set)
+ data.volume_is_absolute = !relative_volume;
+ data.save_volume = TRUE;
+ }
+ if (muted_set) {
pa_sink_input_new_data_set_muted(&data, muted);
+ data.save_muted = TRUE;
+ }
data.sync_base = ssync ? ssync->sink_input : NULL;
data.flags = flags;
@@ -1838,7 +1847,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
early_requests = FALSE,
dont_inhibit_auto_suspend = FALSE,
muted_set = FALSE,
- fail_on_suspend = FALSE;
+ fail_on_suspend = FALSE,
+ relative_volume = FALSE;
pa_sink_input_flags_t flags = 0;
pa_proplist *p;
pa_bool_t volume_set = TRUE;
@@ -1931,6 +1941,15 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
}
}
+ if (c->version >= 17) {
+
+ if (pa_tagstruct_get_boolean(t, &relative_volume) < 0) {
+ protocol_error(c);
+ pa_proplist_free(p);
+ return;
+ }
+ }
+
if (!pa_tagstruct_eof(t)) {
protocol_error(c);
pa_proplist_free(p);
@@ -1970,7 +1989,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
* flag. For older versions we synthesize it here */
muted_set = muted_set || muted;
- s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
+ s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, relative_volume, &ret);
pa_proplist_free(p);
CHECK_VALIDITY(c->pstream, s, tag, ret);
diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c
index 745c7de0..5bf72ed0 100644
--- a/src/pulsecore/svolume_mmx.c
+++ b/src/pulsecore/svolume_mmx.c
@@ -25,6 +25,8 @@
#endif
#include <pulse/timeval.h>
+#include <pulse/rtclock.h>
+
#include <pulsecore/random.h>
#include <pulsecore/macro.h>
#include <pulsecore/g711.h>
@@ -287,6 +289,8 @@ static void run_test (void) {
}
stop = pa_rtclock_now();
pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+
+ pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
}
#endif
diff --git a/src/pulsecore/svolume_sse.c b/src/pulsecore/svolume_sse.c
index 1cc4e0aa..620524fa 100644
--- a/src/pulsecore/svolume_sse.c
+++ b/src/pulsecore/svolume_sse.c
@@ -25,6 +25,8 @@
#endif
#include <pulse/timeval.h>
+#include <pulse/rtclock.h>
+
#include <pulsecore/random.h>
#include <pulsecore/macro.h>
#include <pulsecore/g711.h>
@@ -261,7 +263,7 @@ static void run_test (void) {
func = pa_get_volume_func (PA_SAMPLE_S16NE);
- printf ("checking SSE %zd\n", sizeof (samples));
+ printf ("checking SSE2 %zd\n", sizeof (samples));
pa_random (samples, sizeof (samples));
memcpy (samples_ref, samples, sizeof (samples));
@@ -273,7 +275,7 @@ static void run_test (void) {
volumes[i] = volumes[padding];
func (samples_ref, volumes, CHANNELS, sizeof (samples));
- pa_volume_s16ne_sse (samples, volumes, CHANNELS, sizeof (samples));
+ pa_volume_s16ne_sse2 (samples, volumes, CHANNELS, sizeof (samples));
for (i = 0; i < SAMPLES; i++) {
if (samples[i] != samples_ref[i]) {
printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i],
@@ -284,7 +286,7 @@ static void run_test (void) {
start = pa_rtclock_now();
for (j = 0; j < TIMES; j++) {
memcpy (samples, samples_orig, sizeof (samples));
- pa_volume_s16ne_sse (samples, volumes, CHANNELS, sizeof (samples));
+ pa_volume_s16ne_sse2 (samples, volumes, CHANNELS, sizeof (samples));
}
stop = pa_rtclock_now();
pa_log_info("SSE: %llu usec.", (long long unsigned int)(stop - start));
@@ -296,6 +298,8 @@ static void run_test (void) {
}
stop = pa_rtclock_now();
pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+
+ pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
}
#endif
#endif /* defined (__i386__) || defined (__amd64__) */
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index d6c37878..1371ad56 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -196,6 +196,13 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
int64_t ax = 0, ay = 0, k, t;
double r;
+ /* FIXME: Optimization: Jason Newton suggested that instead of
+ * going through the history on each iteration we could calculated
+ * avg_gradient() as we go.
+ *
+ * Second idea: it might make sense to weight history entries:
+ * more recent entries should matter more than old ones. */
+
/* Too few measurements, assume gradient of 1 */
if (s->n_history < s->min_history)
return 1;
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 141ab5b1..ee67c425 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -44,8 +44,6 @@
#include <pulsecore/log.h>
#include <pulsecore/sndfile-util.h>
-#define BUFSIZE (16*1024)
-
static pa_context *context = NULL;
static pa_mainloop_api *mainloop_api = NULL;
@@ -158,10 +156,23 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
return;
}
+ printf(_("Server String: %s\n"
+ "Library Protocol Version: %u\n"
+ "Server Protocol Version: %u\n"
+ "Is Local: %s\n"
+ "Client Index: %u\n"
+ "Tile Size: %zu\n"),
+ pa_context_get_server(c),
+ pa_context_get_protocol_version(c),
+ pa_context_get_server_protocol_version(c),
+ pa_yes_no(pa_context_is_local(c)),
+ pa_context_get_index(c),
+ pa_context_get_tile_size(c, NULL));
+
pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
- printf(_("User name: %s\n"
+ printf(_("User Name: %s\n"
"Host Name: %s\n"
"Server Name: %s\n"
"Server Version: %s\n"
@@ -169,7 +180,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
"Default Channel Map: %s\n"
"Default Sink: %s\n"
"Default Source: %s\n"
- "Cookie: %08x\n"),
+ "Cookie: %04x:%04x\n"),
i->user_name,
i->host_name,
i->server_name,
@@ -178,7 +189,8 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
cm,
i->default_sink_name,
i->default_source_name,
- i->cookie);
+ i->cookie >> 16,
+ i->cookie & 0xFFFFU);
complete_action();
}
diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
index c327ee41..534b77b4 100644
--- a/src/utils/pasuspender.c
+++ b/src/utils/pasuspender.c
@@ -45,8 +45,6 @@
#include <pulse/pulseaudio.h>
#include <pulsecore/macro.h>
-#define BUFSIZE 1024
-
static pa_context *context = NULL;
static pa_mainloop_api *mainloop_api = NULL;
static char **child_argv = NULL;