summaryrefslogtreecommitdiffstats
path: root/src/pulsecore
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore')
-rw-r--r--src/pulsecore/cli-text.c30
-rw-r--r--src/pulsecore/core-util.c24
-rw-r--r--src/pulsecore/core-util.h3
-rw-r--r--src/pulsecore/endianmacros.h18
-rw-r--r--src/pulsecore/memblock.c5
-rw-r--r--src/pulsecore/pdispatch.c92
-rw-r--r--src/pulsecore/protocol-native.c13
-rw-r--r--src/pulsecore/sample-util.c64
-rw-r--r--src/pulsecore/sample-util.h4
-rw-r--r--src/pulsecore/sink.c12
-rw-r--r--src/pulsecore/sink.h2
-rw-r--r--src/pulsecore/source.c4
-rw-r--r--src/pulsecore/source.h2
-rw-r--r--src/pulsecore/tagstruct.c38
-rw-r--r--src/pulsecore/tagstruct.h6
15 files changed, 285 insertions, 32 deletions
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 7bbc2660..362a9791 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -115,7 +115,12 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX],
+ cv[PA_CVOLUME_SNPRINT_MAX],
+ cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
+ v[PA_VOLUME_SNPRINT_MAX],
+ vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
+ cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
pa_usec_t min_latency, max_latency;
pa_sink_get_latency_range(sink, &min_latency, &max_latency);
@@ -127,7 +132,8 @@ char *pa_sink_list_to_string(pa_core *c) {
"\tdriver: <%s>\n"
"\tflags: %s%s%s%s%s%s\n"
"\tstate: %s\n"
- "\tvolume: %s\n"
+ "\tvolume: %s%s%s\n"
+ "\tbase volume: %s%s%s\n"
"\tmuted: %s\n"
"\tcurrent latency: %0.2f ms\n"
"\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
@@ -150,6 +156,11 @@ char *pa_sink_list_to_string(pa_core *c) {
sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
state_table[pa_sink_get_state(sink)],
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, 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)) : "",
+ pa_volume_snprint(v, sizeof(v), sink->base_volume),
+ sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
+ sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), sink->base_volume) : "",
pa_yes_no(pa_sink_get_mute(sink, FALSE)),
(double) pa_sink_get_latency(sink) / (double) PA_USEC_PER_MSEC,
(double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC,
@@ -192,7 +203,12 @@ char *pa_source_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
- char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], *t;
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX],
+ cv[PA_CVOLUME_SNPRINT_MAX],
+ cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
+ v[PA_VOLUME_SNPRINT_MAX],
+ vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
+ cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
pa_usec_t min_latency, max_latency;
pa_source_get_latency_range(source, &min_latency, &max_latency);
@@ -204,7 +220,8 @@ char *pa_source_list_to_string(pa_core *c) {
"\tdriver: <%s>\n"
"\tflags: %s%s%s%s%s%s\n"
"\tstate: %s\n"
- "\tvolume: %s\n"
+ "\tvolume: %s%s%s\n"
+ "\tbase volume: %s%s%s\n"
"\tmuted: %s\n"
"\tcurrent latency: %0.2f ms\n"
"\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
@@ -225,6 +242,11 @@ char *pa_source_list_to_string(pa_core *c) {
source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
state_table[pa_source_get_state(source)],
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)) : "",
+ pa_volume_snprint(v, sizeof(v), source->base_volume),
+ source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
+ source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), source->base_volume) : "",
pa_yes_no(pa_source_get_mute(source, FALSE)),
(double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
(double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC,
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index dde34d7b..6f315666 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2487,3 +2487,27 @@ pa_bool_t pa_in_valgrind(void) {
return b > 1;
}
#endif
+
+unsigned pa_gcd(unsigned a, unsigned b) {
+
+ while (b > 0) {
+ unsigned t = b;
+ b = a % b;
+ a = t;
+ }
+
+ return a;
+}
+
+void pa_reduce(unsigned *num, unsigned *den) {
+
+ unsigned gcd = pa_gcd(*num, *den);
+
+ if (gcd <= 0)
+ return;
+
+ *num /= gcd;
+ *den /= gcd;
+
+ pa_assert(pa_gcd(*num, *den) == 1);
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index fd6ee896..d9fad11e 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -206,4 +206,7 @@ static inline pa_bool_t pa_in_valgrind(void) {
}
#endif
+unsigned pa_gcd(unsigned a, unsigned b);
+void pa_reduce(unsigned *num, unsigned *den);
+
#endif
diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index 1b94de17..85bebd68 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -39,10 +39,10 @@
#define PA_INT32_SWAP(x) ((int32_t) bswap_32((uint32_t) x))
#define PA_UINT32_SWAP(x) ((uint32_t) bswap_32((uint32_t) x))
#else
-#define PA_INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
-#define PA_UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
-#define PA_INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
-#define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
+#define PA_INT16_SWAP(x) ( (int16_t) ( ((uint16_t) (x) >> 8) | ((uint16_t) (x) << 8) ) )
+#define PA_UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) (x) >> 8) | ((uint16_t) (x) << 8) ) )
+#define PA_INT32_SWAP(x) ( (int32_t) ( ((uint32_t) (x) >> 24) | ((uint32_t) (x) << 24) | (((uint32_t) (x) & 0xFF00) << 8) | ((((uint32_t) (x)) >> 8) & 0xFF00) ) )
+#define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) (x) >> 24) | ((uint32_t) (x) << 24) | (((uint32_t) (x) & 0xFF00) << 8) | ((((uint32_t) (x)) >> 8) & 0xFF00) ) )
#endif
static inline float PA_FLOAT32_SWAP(float x) {
@@ -56,13 +56,13 @@ static inline float PA_FLOAT32_SWAP(float x) {
return t.f;
}
-#define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x)
-#define PA_MAYBE_UINT16_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x)
+#define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : (x))
+#define PA_MAYBE_UINT16_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : (x))
-#define PA_MAYBE_INT32_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x)
-#define PA_MAYBE_UINT32_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x)
+#define PA_MAYBE_INT32_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : (x))
+#define PA_MAYBE_UINT32_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : (x))
-#define PA_MAYBE_FLOAT32_SWAP(c,x) ((c) ? PA_FLOAT32_SWAP(x) : x)
+#define PA_MAYBE_FLOAT32_SWAP(c,x) ((c) ? PA_FLOAT32_SWAP(x) : (x))
#ifdef WORDS_BIGENDIAN
#define PA_INT16_FROM_LE(x) PA_INT16_SWAP(x)
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index d9e1bf1c..1d7f4559 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -711,11 +711,12 @@ pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) {
return NULL;
}
- pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s",
+ pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s, maximum usable slot size is %lu",
p->memory.shared ? "shared" : "private",
p->n_blocks,
pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size),
- pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size)));
+ pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size)),
+ (unsigned long) pa_mempool_block_size_max(p));
memset(&p->stat, 0, sizeof(p->stat));
pa_atomic_store(&p->n_init, 0);
diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index 00df0f79..a5b33d62 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -40,34 +40,35 @@
#include "pdispatch.h"
-/*#define DEBUG_OPCODES */
+/* #define DEBUG_OPCODES */
#ifdef DEBUG_OPCODES
static const char *command_names[PA_COMMAND_MAX] = {
+ /* Generic commands */
[PA_COMMAND_ERROR] = "ERROR",
[PA_COMMAND_TIMEOUT] = "TIMEOUT",
[PA_COMMAND_REPLY] = "REPLY",
+
+ /* CLIENT->SERVER */
[PA_COMMAND_CREATE_PLAYBACK_STREAM] = "CREATE_PLAYBACK_STREAM",
[PA_COMMAND_DELETE_PLAYBACK_STREAM] = "DELETE_PLAYBACK_STREAM",
[PA_COMMAND_CREATE_RECORD_STREAM] = "CREATE_RECORD_STREAM",
[PA_COMMAND_DELETE_RECORD_STREAM] = "DELETE_RECORD_STREAM",
[PA_COMMAND_AUTH] = "AUTH",
- [PA_COMMAND_REQUEST] = "REQUEST",
[PA_COMMAND_EXIT] = "EXIT",
[PA_COMMAND_SET_CLIENT_NAME] = "SET_CLIENT_NAME",
[PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK",
[PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE",
[PA_COMMAND_DRAIN_PLAYBACK_STREAM] = "DRAIN_PLAYBACK_STREAM",
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = "PLAYBACK_STREAM_KILLED",
- [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED",
[PA_COMMAND_STAT] = "STAT",
- [PA_COMMAND_GET_PLAYBACK_LATENCY] = "PLAYBACK_LATENCY",
+ [PA_COMMAND_GET_PLAYBACK_LATENCY] = "GET_PLAYBACK_LATENCY",
[PA_COMMAND_CREATE_UPLOAD_STREAM] = "CREATE_UPLOAD_STREAM",
[PA_COMMAND_DELETE_UPLOAD_STREAM] = "DELETE_UPLOAD_STREAM",
[PA_COMMAND_FINISH_UPLOAD_STREAM] = "FINISH_UPLOAD_STREAM",
[PA_COMMAND_PLAY_SAMPLE] = "PLAY_SAMPLE",
[PA_COMMAND_REMOVE_SAMPLE] = "REMOVE_SAMPLE",
+
[PA_COMMAND_GET_SERVER_INFO] = "GET_SERVER_INFO",
[PA_COMMAND_GET_SINK_INFO] = "GET_SINK_INFO",
[PA_COMMAND_GET_SINK_INFO_LIST] = "GET_SINK_INFO_LIST",
@@ -84,15 +85,87 @@ static const char *command_names[PA_COMMAND_MAX] = {
[PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = "GET_SOURCE_OUTPUT_INFO",
[PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = "GET_SOURCE_OUTPUT_INFO_LIST",
[PA_COMMAND_SUBSCRIBE] = "SUBSCRIBE",
- [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT",
+
[PA_COMMAND_SET_SINK_VOLUME] = "SET_SINK_VOLUME",
[PA_COMMAND_SET_SINK_INPUT_VOLUME] = "SET_SINK_INPUT_VOLUME",
[PA_COMMAND_SET_SOURCE_VOLUME] = "SET_SOURCE_VOLME",
+
+ [PA_COMMAND_SET_SINK_MUTE] = "SET_SINK_MUTE",
+ [PA_COMMAND_SET_SOURCE_MUTE] = "SET_SOURCE_MUTE",
+
[PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = "TRIGGER_PLAYBACK_STREAM",
[PA_COMMAND_FLUSH_PLAYBACK_STREAM] = "FLUSH_PLAYBACK_STREAM",
[PA_COMMAND_CORK_PLAYBACK_STREAM] = "CORK_PLAYBACK_STREAM",
+
+ [PA_COMMAND_SET_DEFAULT_SINK] = "SET_DEFAULT_SINK",
+ [PA_COMMAND_SET_DEFAULT_SOURCE] = "SET_DEFAULT_SOURCE",
+
+ [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = "SET_PLAYBACK_STREAM_NAME",
+ [PA_COMMAND_SET_RECORD_STREAM_NAME] = "SET_RECORD_STREAM_NAME",
+
+ [PA_COMMAND_KILL_CLIENT] = "KILL_CLIENT",
+ [PA_COMMAND_KILL_SINK_INPUT] = "KILL_SINK_INPUT",
+ [PA_COMMAND_KILL_SOURCE_OUTPUT] = "SOURCE_OUTPUT",
+
+ [PA_COMMAND_LOAD_MODULE] = "LOAD_MODULE",
+ [PA_COMMAND_UNLOAD_MODULE] = "UNLOAD_MODULE",
+
+ [PA_COMMAND_ADD_AUTOLOAD] = "ADD_AUTOLOAD",
+ [PA_COMMAND_REMOVE_AUTOLOAD] = "REMOVE_AUTOLOAD",
[PA_COMMAND_GET_AUTOLOAD_INFO] = "GET_AUTOLOAD_INFO",
[PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = "GET_AUTOLOAD_INFO_LIST",
+
+ [PA_COMMAND_GET_RECORD_LATENCY] = "GET_RECORD_LATENCY",
+ [PA_COMMAND_CORK_RECORD_STREAM] = "CORK_RECORD_STREAM",
+ [PA_COMMAND_FLUSH_RECORD_STREAM] = "FLUSH_RECORD_STREAM",
+ [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = "PREBUF_PLAYBACK_STREAM",
+
+ /* SERVER->CLIENT */
+ [PA_COMMAND_REQUEST] = "REQUEST",
+ [PA_COMMAND_OVERFLOW] = "OVERFLOW",
+ [PA_COMMAND_UNDERFLOW] = "UNDERFLOW",
+ [PA_COMMAND_PLAYBACK_STREAM_KILLED] = "PLAYBACK_STREAM_KILLED",
+ [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED",
+ [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT",
+
+ /* A few more client->server commands */
+
+ /* Supported since protocol v10 (0.9.5) */
+ [PA_COMMAND_MOVE_SINK_INPUT] = "MOVE_SINK_INPUT",
+ [PA_COMMAND_MOVE_SOURCE_OUTPUT] = "MOVE_SOURCE_OUTPUT",
+
+ /* Supported since protocol v11 (0.9.7) */
+ [PA_COMMAND_SET_SINK_INPUT_MUTE] = "SET_SINK_INPUT_MUTE",
+
+ [PA_COMMAND_SUSPEND_SINK] = "SUSPEND_SINK",
+ [PA_COMMAND_SUSPEND_SOURCE] = "SUSPEND_SOURCE",
+
+ /* Supported since protocol v12 (0.9.8) */
+ [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = "SET_PLAYBACK_STREAM_BUFFER_ATTR",
+ [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = "SET_RECORD_STREAM_BUFFER_ATTR",
+
+ [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = "UPDATE_PLAYBACK_STREAM_SAMPLE_RATE",
+ [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = "UPDATE_RECORD_STREAM_SAMPLE_RATE",
+
+ /* SERVER->CLIENT */
+ [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = "PLAYBACK_STREAM_SUSPENDED",
+ [PA_COMMAND_RECORD_STREAM_SUSPENDED] = "RECORD_STREAM_SUSPENDED",
+ [PA_COMMAND_PLAYBACK_STREAM_MOVED] = "PLAYBACK_STREAM_MOVED",
+ [PA_COMMAND_RECORD_STREAM_MOVED] = "RECORD_STREAM_MOVED",
+
+ /* Supported since protocol v13 (0.9.11) */
+ [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = "UPDATE_RECORD_STREAM_PROPLIST",
+ [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = "UPDATE_RECORD_STREAM_PROPLIST",
+ [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = "UPDATE_CLIENT_PROPLIST",
+ [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = "REMOVE_RECORD_STREAM_PROPLIST",
+ [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = "REMOVE_PLAYBACK_STREAM_PROPLIST",
+ [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = "REMOVE_CLIENT_PROPLIST",
+
+ /* SERVER->CLIENT */
+ [PA_COMMAND_STARTED] = "STARTED",
+
+ /* Supported since protocol v14 (0.9.12) */
+ [PA_COMMAND_EXTENSION] = "EXTENSION"
};
#endif
@@ -213,11 +286,12 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
#ifdef DEBUG_OPCODES
{
char t[256];
- char const *p;
- if (!(p = command_names[command]))
+ char const *p = NULL;
+
+ if (command >= PA_COMMAND_MAX || !(p = command_names[command]))
pa_snprintf((char*) (p = t), sizeof(t), "%u", command);
- pa_log("Recieved opcode <%s>", p);
+ pa_log("[%p] Recieved opcode <%s>", pd, p);
}
#endif
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 56e86cb4..3c1e5761 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2677,6 +2677,9 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin
pa_tagstruct_put_proplist(t, sink->proplist);
pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
}
+
+ if (c->version >= 15)
+ pa_tagstruct_put_volume(t, sink->base_volume);
}
static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
@@ -2708,8 +2711,10 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s
pa_tagstruct_put_proplist(t, source->proplist);
pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
}
-}
+ if (c->version >= 15)
+ pa_tagstruct_put_volume(t, source->base_volume);
+}
static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
pa_assert(t);
@@ -3963,7 +3968,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
}
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, !name || pa_namereg_is_valid_name(name) || *name == 0, 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);
@@ -3972,6 +3977,8 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
if (idx == PA_INVALID_INDEX && name && !*name) {
+ pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
+
if (pa_sink_suspend_all(c->protocol->core, b) < 0) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
return;
@@ -3997,6 +4004,8 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
if (idx == PA_INVALID_INDEX && name && !*name) {
+ pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
+
if (pa_source_suspend_all(c->protocol->core, b) < 0) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
return;
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 9f0f795c..3be08efd 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -27,6 +27,8 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
#include <liboil/liboilfuncs.h>
#include <liboil/liboil.h>
@@ -34,8 +36,10 @@
#include <pulse/timeval.h>
#include <pulsecore/log.h>
+#include <pulsecore/core-error.h>
#include <pulsecore/macro.h>
#include <pulsecore/g711.h>
+#include <pulsecore/core-util.h>
#include "sample-util.h"
#include "endianmacros.h"
@@ -477,7 +481,6 @@ size_t pa_mix(
case PA_SAMPLE_FLOAT32RE: {
unsigned channel = 0;
- float linear[PA_CHANNELS_MAX];
calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
@@ -987,3 +990,62 @@ size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
return (size_t) u;
}
+
+void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
+ FILE *f;
+ void *p;
+
+ pa_assert(c);
+ pa_assert(fn);
+
+ /* Only for debugging purposes */
+
+ f = fopen(fn, "a");
+
+ if (!f) {
+ pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
+ return;
+ }
+
+ p = pa_memblock_acquire(c->memblock);
+
+ if (fwrite((uint8_t*) p + c->index, 1, c->length, f) != c->length)
+ pa_log_warn("Failed to write to '%s': %s", fn, pa_cstrerror(errno));
+
+ pa_memblock_release(c->memblock);
+
+ fclose(f);
+}
+
+static void calc_sine(float *f, size_t l, double freq) {
+ size_t i;
+
+ l /= sizeof(float);
+
+ for (i = 0; i < l; i++)
+ *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
+}
+
+void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
+ size_t l;
+ unsigned gcd, n;
+ void *p;
+
+ pa_memchunk_reset(c);
+
+ gcd = pa_gcd(rate, freq);
+ n = rate / gcd;
+
+ l = pa_mempool_block_size_max(pool) / sizeof(float);
+
+ l /= n;
+ if (l <= 0) l = 1;
+ l *= n;
+
+ c->length = l * sizeof(float);
+ c->memblock = pa_memblock_new(pool, c->length);
+
+ p = pa_memblock_acquire(c->memblock);
+ calc_sine(p, c->length, freq * l / rate);
+ pa_memblock_release(c->memblock);
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 2fe2c81d..2230aaf0 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -81,4 +81,8 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo
pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec);
size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec);
+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);
+
#endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 1580cf2e..a4d993cd 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -191,6 +191,7 @@ pa_sink* pa_sink_new(
s->n_corked = 0;
s->volume = data->volume;
+ s->base_volume = PA_VOLUME_NORM;
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
@@ -239,7 +240,7 @@ pa_sink* pa_sink_new(
pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
- s->monitor_source = pa_source_new(core, &source_data, 0);
+ s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
pa_source_new_data_done(&source_data);
@@ -835,6 +836,9 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
if (!PA_SINK_IS_OPENED(s->state))
return 0;
+ if (!(s->flags & PA_SINK_LATENCY))
+ return 0;
+
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
return usec;
@@ -1161,7 +1165,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
size_t sink_nbytes, total_nbytes;
/* Get the latency of the sink */
- if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+ if (!(s->flags & PA_SINK_LATENCY) ||
+ PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
usec = 0;
sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
@@ -1220,7 +1225,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
size_t nbytes;
/* Get the latency of the sink */
- if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+ if (!(s->flags & PA_SINK_LATENCY) ||
+ PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
usec = 0;
nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index c5a73214..254be3b0 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -81,6 +81,8 @@ struct pa_sink {
pa_cvolume volume;
pa_bool_t muted;
+ pa_volume_t base_volume; /* shall be constant */
+
pa_bool_t refresh_volume:1;
pa_bool_t refresh_muted:1;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f113e295..815ec271 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -185,6 +185,7 @@ pa_source* pa_source_new(
s->volume = data->volume;
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
+ s->base_volume = PA_VOLUME_NORM;
reset_callbacks(s);
s->userdata = NULL;
@@ -500,6 +501,9 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
if (!PA_SOURCE_IS_OPENED(s->state))
return 0;
+ if (!(s->flags & PA_SOURCE_LATENCY))
+ return 0;
+
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
return usec;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index aaf904b4..b93e4ad0 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -84,6 +84,8 @@ struct pa_source {
pa_cvolume volume;
pa_bool_t muted;
+ pa_volume_t base_volume; /* shall be constant */
+
pa_bool_t refresh_volume:1;
pa_bool_t refresh_muted:1;
diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index 62a30144..330b7596 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -254,6 +254,17 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
}
}
+void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t vol) {
+ uint32_t u;
+ pa_assert(t);
+
+ extend(t, 5);
+ t->data[t->length] = PA_TAG_VOLUME;
+ u = htonl((uint32_t) vol);
+ memcpy(t->data+t->length+1, &u, 4);
+ t->length += 5;
+}
+
void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p) {
void *state = NULL;
pa_assert(t);
@@ -555,6 +566,25 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
return 0;
}
+int pa_tagstruct_get_volume(pa_tagstruct*t, pa_volume_t *vol) {
+ uint32_t u;
+
+ pa_assert(t);
+ pa_assert(vol);
+
+ if (t->rindex+5 > t->length)
+ return -1;
+
+ if (t->data[t->rindex] != PA_TAG_VOLUME)
+ return -1;
+
+ memcpy(&u, t->data+t->rindex+1, 4);
+ *vol = (pa_volume_t) ntohl(u);
+
+ t->rindex += 5;
+ return 0;
+}
+
int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
size_t saved_rindex;
@@ -663,6 +693,10 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) {
pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
break;
+ case PA_TAG_VOLUME:
+ pa_tagstruct_put_volume(t, va_arg(va, pa_volume_t));
+ break;
+
case PA_TAG_PROPLIST:
pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
break;
@@ -738,6 +772,10 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
break;
+ case PA_TAG_VOLUME:
+ ret = pa_tagstruct_get_volume(t, va_arg(va, pa_volume_t *));
+ break;
+
case PA_TAG_PROPLIST:
ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
break;
diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h
index e7d07054..19288eeb 100644
--- a/src/pulsecore/tagstruct.h
+++ b/src/pulsecore/tagstruct.h
@@ -54,7 +54,8 @@ enum {
PA_TAG_USEC = 'U' /* 64bit unsigned */,
PA_TAG_CHANNEL_MAP = 'm',
PA_TAG_CVOLUME = 'v',
- PA_TAG_PROPLIST = 'P'
+ PA_TAG_PROPLIST = 'P',
+ PA_TAG_VOLUME = 'V'
};
pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length);
@@ -79,6 +80,7 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume);
void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p);
+void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t volume);
int pa_tagstruct_get(pa_tagstruct *t, ...);
@@ -95,6 +97,6 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v);
int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p);
-
+int pa_tagstruct_get_volume(pa_tagstruct *t, pa_volume_t *v);
#endif