summaryrefslogtreecommitdiffstats
path: root/src/pulse
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulse')
-rw-r--r--src/pulse/channelmap.c13
-rw-r--r--src/pulse/channelmap.h10
-rw-r--r--src/pulse/client-conf.c3
-rw-r--r--src/pulse/client-conf.h1
-rw-r--r--src/pulse/client.conf.in1
-rw-r--r--src/pulse/context.c4
-rw-r--r--src/pulse/introspect.c2
-rw-r--r--src/pulse/sample.c12
-rw-r--r--src/pulse/sample.h11
-rw-r--r--src/pulse/stream.c21
-rw-r--r--src/pulse/volume.c110
-rw-r--r--src/pulse/volume.h44
12 files changed, 209 insertions, 23 deletions
diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index 37308751..fd313bd3 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -466,6 +466,13 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
pa_assert(l > 0);
pa_assert(map);
+ pa_init_i18n();
+
+ if (!pa_channel_map_valid(map)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
*(e = s) = 0;
for (channel = 0; channel < map->channels && l > 1; channel++) {
@@ -562,5 +569,11 @@ int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *s
pa_assert(map);
pa_assert(ss);
+ if (!pa_channel_map_valid(map))
+ return 0;
+
+ if (!pa_sample_spec_valid(ss))
+ return 0;
+
return map->channels == ss->channels;
}
diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index d2dd6f8f..d7d19d79 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -175,7 +175,9 @@ typedef struct pa_channel_map {
/**< Channel labels */
} pa_channel_map;
-/** Initialize the specified channel map and return a pointer to it */
+/** Initialize the specified channel map and return a pointer to
+ * it. The channel map will have a defined state but
+ * pa_channel_map_valid() will fail for it. */
pa_channel_map* pa_channel_map_init(pa_channel_map *m);
/** Initialize the specified channel map for monoaural audio and return a pointer to it */
@@ -202,7 +204,11 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) PA_GCC_PURE
/** Return a human readable text label for the specified channel position. \since 0.9.7 */
const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos);
-/** The maximum length of strings returned by pa_channel_map_snprint() */
+/** The maximum length of strings returned by
+ * pa_channel_map_snprint(). Please note that this value can change
+ * with any release without warning and without being considered API
+ * or ABI breakage. You should not use this definition anywhere where
+ * it might become part of an ABI. */
#define PA_CHANNEL_MAP_SNPRINT_MAX 336
/** Make a humand readable string from the specified channel map */
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index 739ef161..58d64642 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -61,6 +61,7 @@ static const pa_client_conf default_conf = {
.disable_shm = FALSE,
.cookie_file = NULL,
.cookie_valid = FALSE,
+ .shm_size = 0
};
pa_client_conf *pa_client_conf_new(void) {
@@ -99,6 +100,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
{ "autospawn", pa_config_parse_bool, NULL },
{ "cookie-file", pa_config_parse_string, NULL },
{ "disable-shm", pa_config_parse_bool, NULL },
+ { "shm-size-bytes", pa_config_parse_size, NULL },
{ NULL, NULL, NULL },
};
@@ -110,6 +112,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
table[5].data = &c->autospawn;
table[6].data = &c->cookie_file;
table[7].data = &c->disable_shm;
+ table[8].data = &c->shm_size;
if (filename) {
diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h
index 699279aa..4eac467e 100644
--- a/src/pulse/client-conf.h
+++ b/src/pulse/client-conf.h
@@ -31,6 +31,7 @@ typedef struct pa_client_conf {
pa_bool_t autospawn, disable_shm;
uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
pa_bool_t cookie_valid; /* non-zero, when cookie is valid */
+ size_t shm_size;
} pa_client_conf;
/* Create a new configuration data object and reset it to defaults */
diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in
index 8339d651..579bcc20 100644
--- a/src/pulse/client.conf.in
+++ b/src/pulse/client.conf.in
@@ -30,3 +30,4 @@
; cookie-file =
; disable-shm = no
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 154e5faf..3145d9c8 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -174,10 +174,10 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
pa_client_conf_load(c->conf, NULL);
pa_client_conf_env(c->conf);
- if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) {
+ if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) {
if (!c->conf->disable_shm)
- c->mempool = pa_mempool_new(FALSE);
+ c->mempool = pa_mempool_new(FALSE, c->conf->shm_size);
if (!c->mempool) {
context_free(c);
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 4e362fd8..38091581 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -24,6 +24,8 @@
#include <config.h>
#endif
+#include <string.h>
+
#include <pulse/context.h>
#include <pulse/gccmacro.h>
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index 93da2465..29501595 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -80,6 +80,16 @@ size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * pa_frame_size(spec);
}
+pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec) {
+ pa_assert(spec);
+
+ spec->format = PA_SAMPLE_INVALID;
+ spec->rate = 0;
+ spec->channels = 0;
+
+ return spec;
+}
+
int pa_sample_spec_valid(const pa_sample_spec *spec) {
pa_assert(spec);
@@ -131,7 +141,7 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
pa_init_i18n();
if (!pa_sample_spec_valid(spec))
- pa_snprintf(s, l, _("Invalid"));
+ pa_snprintf(s, l, _("(invalid)"));
else
pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 3f1b2fcf..3c7dd0e7 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -232,6 +232,11 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) PA_GCC_P
* return values. \since 0.9 */
size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) PA_GCC_PURE;
+/** Initialize the specified sample spec and return a pointer to
+ * it. The sample spec will have a defined state but
+ * pa_sample_spec_valid() will fail for it. \since 0.9.13 */
+pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec);
+
/** Return non-zero when the sample type specification is valid */
int pa_sample_spec_valid(const pa_sample_spec *spec) PA_GCC_PURE;
@@ -244,7 +249,11 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) PA_GCC_PURE;
/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
pa_sample_format_t pa_parse_sample_format(const char *format) PA_GCC_PURE;
-/** Maximum required string length for pa_sample_spec_snprint() */
+/** Maximum required string length for
+ * pa_sample_spec_snprint(). Please note that this value can change
+ * with any release without warning and without being considered API
+ * or ABI breakage. You should not use this definition anywhere where
+ * it might become part of an ABI. */
#define PA_SAMPLE_SPEC_SNPRINT_MAX 32
/** Pretty print a sample type specification to a string */
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index d0c7d67e..00aa1cf9 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -86,7 +86,7 @@ pa_stream *pa_stream_new_with_proplist(
pa_assert(PA_REFCNT_VALUE(c) >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE && ss->format != PA_SAMPLE_S32BE), PA_ERR_NOTSUPPORTED);
PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
@@ -557,7 +557,7 @@ void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag,
request_auto_timing_update(s, TRUE);
if (s->started_callback)
- s->started_callback(s, s->suspended_userdata);
+ s->started_callback(s, s->started_userdata);
finish:
pa_context_unref(c);
@@ -1851,7 +1851,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
if (s->context->version >= 13) {
pa_proplist *p = pa_proplist_new();
- pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
+ pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
o = pa_stream_proplist_update(s, PA_UPDATE_REPLACE, p, cb, userdata);
pa_proplist_free(p);
} else {
@@ -2010,7 +2010,6 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
success = 0;
} else {
-
if (o->stream->direction == PA_STREAM_PLAYBACK) {
if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 ||
pa_tagstruct_getu32(t, &o->stream->buffer_attr.tlength) < 0 ||
@@ -2027,6 +2026,20 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
}
}
+ if (o->stream->context->version >= 13) {
+ pa_usec_t usec;
+
+ if (pa_tagstruct_get_usec(t, &usec) < 0) {
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->stream->direction == PA_STREAM_RECORD)
+ o->stream->timing_info.configured_source_usec = usec;
+ else
+ o->stream->timing_info.configured_sink_usec = usec;
+ }
+
if (!pa_tagstruct_eof(t)) {
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 15938cbc..99a85f44 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <string.h>
+#include <pulse/i18n.h>
#include <pulsecore/core-util.h>
#include <pulsecore/macro.h>
@@ -46,6 +47,19 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
return 1;
}
+pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
+ unsigned c;
+
+ pa_assert(a);
+
+ a->channels = 0;
+
+ for (c = 0; c < PA_CHANNELS_MAX; c++)
+ a->values[c] = (pa_volume_t) -1;
+
+ return a;
+}
+
pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
int i;
@@ -87,7 +101,16 @@ pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
}
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
- return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b));
+ return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) * pa_sw_volume_to_linear(b));
+}
+
+pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
+ double v = pa_sw_volume_to_linear(b);
+
+ if (v <= 0)
+ return 0;
+
+ return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) / v);
}
#define USER_DECIBEL_RANGE 60
@@ -96,7 +119,7 @@ pa_volume_t pa_sw_volume_from_dB(double dB) {
if (isinf(dB) < 0 || dB <= -USER_DECIBEL_RANGE)
return PA_VOLUME_MUTED;
- return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
+ return (pa_volume_t) lrint((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
}
double pa_sw_volume_to_dB(pa_volume_t v) {
@@ -127,13 +150,20 @@ double pa_sw_volume_to_linear(pa_volume_t v) {
char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
unsigned channel;
- int first = 1;
+ pa_bool_t first = TRUE;
char *e;
pa_assert(s);
pa_assert(l > 0);
pa_assert(c);
+ pa_init_i18n();
+
+ if (!pa_cvolume_valid(c)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
*(e = s) = 0;
for (channel = 0; channel < c->channels && l > 1; channel++) {
@@ -143,7 +173,38 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
(c->values[channel]*100)/PA_VOLUME_NORM);
e = strchr(e, 0);
- first = 0;
+ first = FALSE;
+ }
+
+ return s;
+}
+
+char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
+ unsigned channel;
+ pa_bool_t first = TRUE;
+ char *e;
+
+ pa_assert(s);
+ pa_assert(l > 0);
+ pa_assert(c);
+
+ pa_init_i18n();
+
+ if (!pa_cvolume_valid(c)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ *(e = s) = 0;
+
+ for (channel = 0; channel < c->channels && l > 1; channel++) {
+ l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
+ first ? "" : " ",
+ channel,
+ pa_sw_volume_to_dB(c->values[channel]));
+
+ e = strchr(e, 0);
+ first = FALSE;
}
return s;
@@ -168,12 +229,23 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
pa_assert(a);
pa_assert(b);
- for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) {
+ for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++)
+ dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
- dest->values[i] = pa_sw_volume_multiply(
- i < a->channels ? a->values[i] : PA_VOLUME_NORM,
- i < b->channels ? b->values[i] : PA_VOLUME_NORM);
- }
+ dest->channels = (uint8_t) i;
+
+ return dest;
+}
+
+pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
+ unsigned i;
+
+ pa_assert(dest);
+ pa_assert(a);
+ pa_assert(b);
+
+ for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++)
+ dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
dest->channels = (uint8_t) i;
@@ -181,11 +253,17 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
}
int pa_cvolume_valid(const pa_cvolume *v) {
+ unsigned c;
+
pa_assert(v);
if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX)
return 0;
+ for (c = 0; c < v->channels; c++)
+ if (v->values[c] == (pa_volume_t) -1)
+ return 0;
+
return 1;
}
@@ -273,3 +351,17 @@ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map
*v = result;
return v;
}
+
+int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
+
+ pa_assert(v);
+ pa_assert(ss);
+
+ if (!pa_cvolume_valid(v))
+ return 0;
+
+ if (!pa_sample_spec_valid(ss))
+ return 0;
+
+ return v->channels == ss->channels;
+}
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index d612c7f9..75051af5 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -116,6 +116,11 @@ typedef struct pa_cvolume {
/** Return non-zero when *a == *b */
int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE;
+/** Initialize the specified volume and return a pointer to
+ * it. The sample spec will have a defined state but
+ * pa_cvolume_valid() will fail for it. \since 0.9.13 */
+pa_cvolume* pa_cvolume_init(pa_cvolume *a);
+
/** Set the volume of all channels to PA_VOLUME_NORM */
#define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM)
@@ -125,12 +130,26 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE;
/** Set the volume of all channels to the specified parameter */
pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v);
-/** Maximum length of the strings returned by pa_cvolume_snprint() */
-#define PA_CVOLUME_SNPRINT_MAX 64
+/** Maximum length of the strings returned by
+ * pa_cvolume_snprint(). Please note that this value can change with
+ * any release without warning and without being considered API or ABI
+ * breakage. You should not use this definition anywhere where it
+ * might become part of an ABI.*/
+#define PA_CVOLUME_SNPRINT_MAX 320
/** Pretty print a volume structure */
char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
+/** Maximum length of the strings returned by
+ * pa_cvolume_snprint_dB(). Please note that this value can change with
+ * any release without warning and without being considered API or ABI
+ * breakage. You should not use this definition anywhere where it
+ * might become part of an ABI. \since 0.9.13 */
+#define PA_SW_CVOLUME_SNPRINT_DB_MAX 448
+
+/** Pretty print a volume structure but show dB values. \since 0.9.13 */
+char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c);
+
/** Return the average volume of all channels */
pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE;
@@ -149,12 +168,25 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) PA_GCC_PURE
/** Return 1 if the specified volume has all channels on normal level */
#define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM)
-/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. This is only valid for software volumes! */
+/** Multiply two volume specifications, return the result. This uses
+ * PA_VOLUME_NORM as neutral element of multiplication. This is only
+ * valid for software volumes! */
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) PA_GCC_CONST;
-/** Multiply to per-channel volumes and return the result in *dest. This is only valid for software volumes! */
+/** Multiply two per-channel volumes and return the result in
+ * *dest. This is only valid for software volumes! */
pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
+/** Divide two volume specifications, return the result. This uses
+ * PA_VOLUME_NORM as neutral element of division. This is only valid
+ * for software volumes! If a division by zero is tried the result
+ * will be 0. \since 0.9.13 */
+pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) PA_GCC_CONST;
+
+/** Multiply to per-channel volumes and return the result in
+ * *dest. This is only valid for software volumes! \since 0.9.13 */
+pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
+
/** Convert a decibel value to a volume. This is only valid for software volumes! */
pa_volume_t pa_sw_volume_from_dB(double f) PA_GCC_CONST;
@@ -177,6 +209,10 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
/** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */
pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to);
+/** Return non-zero if the specified volume is compatible with
+ * the specified sample spec. \since 0.9.13 */
+int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) PA_GCC_PURE;
+
PA_C_DECL_END
#endif