diff options
Diffstat (limited to 'src/pulse')
-rw-r--r-- | src/pulse/channelmap.c | 13 | ||||
-rw-r--r-- | src/pulse/channelmap.h | 10 | ||||
-rw-r--r-- | src/pulse/client-conf.c | 3 | ||||
-rw-r--r-- | src/pulse/client-conf.h | 1 | ||||
-rw-r--r-- | src/pulse/client.conf.in | 1 | ||||
-rw-r--r-- | src/pulse/context.c | 4 | ||||
-rw-r--r-- | src/pulse/introspect.c | 2 | ||||
-rw-r--r-- | src/pulse/sample.c | 12 | ||||
-rw-r--r-- | src/pulse/sample.h | 11 | ||||
-rw-r--r-- | src/pulse/stream.c | 21 | ||||
-rw-r--r-- | src/pulse/volume.c | 110 | ||||
-rw-r--r-- | src/pulse/volume.h | 44 |
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 |