[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.19-198-g754644f
Lennart Poettering
gitmailer-noreply at 0pointer.de
Wed Oct 28 17:54:30 PDT 2009
This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.
The master branch has been updated
from e9ccc61a2f561c37939e34a192bd7bd953eb8cbc (commit)
- Log -----------------------------------------------------------------
754644f Merge remote branch 'origin/master'
e7e4e44 simd: update test cases
2edb4df smoother: add comments about optimization recommendations from Jason Newton
f27a506 libpulse: introduce PA_STREAM_RELATIVE_VOLUME
546bcf3 protocol-native: if a client set volume/mute/device store it since it is user input
2501687 libpulse: explain semantics of pa_stream_connect_playback() in more detail
27c6a80 protocol-native: declare that user configured volumes are always absolute
78984e4 pactl: format cookie a little bit nicer
8678f56 pactl: include information about client context in pactl stat output
7c55d6e clients: drop definition of BUFSIZE which is unused
4538523 libpulse: introduce pa_context_get_tile_size() call
744490a memblock: decrease tile size to 64k again
d25b9ea module-equalizer-sink: drop source executable permissions configure.ac: add enable/disable + summary line for fftw
8f2289c module-equalizer-sink: *fixed SSE2 optimized dsp logic (default if available) *cleaned up whitespace formatting (again)
781eb59 module-equalizer-sink: fixed equalizer state save/restore
-----------------------------------------------------------------------
Summary of changes:
PROTOCOL | 6 ++++++
configure.ac | 2 +-
src/map-file | 1 +
src/pulse/context.c | 17 +++++++++++++++++
src/pulse/context.h | 22 +++++++++++++++++++---
src/pulse/def.h | 10 +++++++++-
src/pulse/stream.c | 10 +++++++++-
src/pulse/stream.h | 17 ++++++++++++++++-
src/pulsecore/memblock.c | 2 +-
src/pulsecore/protocol-native.c | 29 ++++++++++++++++++++++++-----
src/pulsecore/svolume_mmx.c | 4 ++++
src/pulsecore/svolume_sse.c | 10 +++++++---
src/pulsecore/time-smoother.c | 7 +++++++
src/utils/pactl.c | 22 +++++++++++++++++-----
src/utils/pasuspender.c | 2 --
15 files changed, 138 insertions(+), 23 deletions(-)
-----------------------------------------------------------------------
commit 781eb594bb77ea814976c6628483b7ba9de2db70
Author: Jason Newton <nevion at gmail.com>
Date: Thu Oct 8 20:46:52 2009 -0700
module-equalizer-sink: fixed equalizer state save/restore
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index 3a28b49..f5c1fb7 100755
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -814,33 +814,35 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
static void pack(char **strs, size_t len, char **packed, size_t *length){
size_t t_len = 0;
size_t headers = (1+len) * sizeof(uint16_t);
- size_t offset = sizeof(uint16_t);
+ char *p;
for(size_t i = 0; i < len; ++i){
t_len += strlen(strs[i]);
}
*length = headers + t_len;
- *packed = pa_xmalloc0(*length);
- ((uint16_t *) *packed)[0] = (uint16_t) len;
+ p = *packed = pa_xmalloc0(*length);
+ *((uint16_t *) p) = (uint16_t) len;
+ p += sizeof(uint16_t);
for(size_t i = 0; i < len; ++i){
uint16_t l = strlen(strs[i]);
- *((uint16_t *)(*packed + offset)) = l;
- offset += sizeof(uint16_t);
- memcpy(*packed + offset, strs[i], l);
- offset += l;
+ *((uint16_t *) p) = (uint16_t) l;
+ p += sizeof(uint16_t);
+ memcpy(p, strs[i], l);
+ p += l;
}
}
static void unpack(char *str, size_t length, char ***strs, size_t *len){
- size_t offset = sizeof(uint16_t);
- *len = ((uint16_t *)str)[0];
+ char *p = str;
+ *len = *((uint16_t *) p);
+ p += sizeof(uint16_t);
*strs = pa_xnew(char *, *len);
+
for(size_t i = 0; i < *len; ++i){
- size_t l = *((uint16_t *)(str+offset));
- size_t e = PA_MIN(offset + l, length) - offset;
- offset = PA_MIN(offset + sizeof(uint16_t), length);
- (*strs)[i] = pa_xnew(char, e + 1);
- memcpy((*strs)[i], str + offset, e);
- (*strs)[i][e] = '\0';
- offset += l;
+ size_t l = *((uint16_t *) p);
+ p += sizeof(uint16_t);
+ (*strs)[i] = pa_xnew(char, l + 1);
+ memcpy((*strs)[i], p, l);
+ (*strs)[i][l] = '\0';
+ p += l;
}
}
static void save_profile(struct userdata *u, size_t channel, char *name){
@@ -885,17 +887,17 @@ static void save_state(struct userdata *u){
pack(u->base_profiles, u->channels, &packed, &packed_length);
state = (float *) pa_xmalloc0(filter_state_size + packed_length);
+ memcpy(state + FILTER_STATE_SIZE, packed, packed_length);
+ pa_xfree(packed);
for(size_t c = 0; c < u->channels; ++c){
a_i = pa_aupdate_read_begin(u->a_H[c]);
- state[c * CHANNEL_PROFILE_SIZE] = u->Xs[a_i][c];
+ state[c * CHANNEL_PROFILE_SIZE] = u->Xs[c][a_i];
H = u->Hs[c][a_i];
- H_n = state + c * CHANNEL_PROFILE_SIZE + 1;
+ H_n = &state[c * CHANNEL_PROFILE_SIZE + 1];
memcpy(H_n, H, FILTER_SIZE * sizeof(float));
pa_aupdate_read_end(u->a_H[c]);
}
- memcpy(((char *)state) + filter_state_size, packed, packed_length);
- pa_xfree(packed);
key.data = state_name;
key.size = strlen(key.data);
@@ -978,13 +980,13 @@ static void load_state(struct userdata *u){
memcpy(u->Hs[c][a_i], H, FILTER_SIZE * sizeof(float));
pa_aupdate_write_end(u->a_H[c]);
}
- //unpack(((char *)value.data) + FILTER_STATE_SIZE, value.size - FILTER_STATE_SIZE, &names, &n_profs);
- //n_profs = PA_MIN(n_profs, u->channels);
- //for(size_t c = 0; c < n_profs; ++c){
- // pa_xfree(u->base_profiles[c]);
- // u->base_profiles[c] = names[c];
- //}
- //pa_xfree(names);
+ unpack(((char *)value.data) + FILTER_STATE_SIZE * sizeof(float), value.size - FILTER_STATE_SIZE * sizeof(float), &names, &n_profs);
+ n_profs = PA_MIN(n_profs, u->channels);
+ for(size_t c = 0; c < n_profs; ++c){
+ pa_xfree(u->base_profiles[c]);
+ u->base_profiles[c] = names[c];
+ }
+ pa_xfree(names);
}
pa_datum_free(&value);
}else{
commit 8f2289c563090562d194c6336ccf4ba75a1eacd0
Author: Jason Newton <nevion at gmail.com>
Date: Sun Oct 18 14:52:32 2009 -0700
module-equalizer-sink:
*fixed SSE2 optimized dsp logic (default if available)
*cleaned up whitespace formatting (again)
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index f5c1fb7..814a00f 100755
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -337,7 +337,7 @@ static void sink_set_mute_cb(pa_sink *s) {
pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);
}
-
+#ifndef __SSE2__
//reference implementation
static void dsp_logic(
float * restrict dst,//used as a temp array too, needs to be fft_length!
@@ -351,12 +351,12 @@ static void dsp_logic(
fftwf_complex * restrict output_window,//The transformed window'd src
struct userdata *u){
//use a linear-phase sliding STFT and overlap-add method (for each channel)
- //zero padd the data
- memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
//window the data
for(size_t j = 0; j < u->window_size; ++j){
dst[j] = X * W[j] * src[j];
}
+ //zero padd the the remaining fft window
+ memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
//Processing is done here!
//do fft
fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
@@ -390,112 +390,104 @@ static void dsp_logic(
(u->samples_gathered - u->R) * sizeof(float)
);
}
-
+#else
typedef float v4sf __attribute__ ((__aligned__(v_size * sizeof(float))));
typedef union float_vector {
float f[v_size];
v4sf v;
-#ifdef __SSE2__
__m128 m;
-#endif
} float_vector_t;
-////regardless of sse enabled, the loops in here assume
-////16 byte aligned addresses and memory allocations divisible by v_size
-//void dsp_logic(
-// float * restrict dst,//used as a temp array too, needs to be fft_length!
-// float * restrict src,/*input data w/ overlap at start,
-// *automatically cycled in routine
-// */
-// float * restrict overlap,//The size of the overlap
-// const float X,//multipliar
-// const float * restrict H,//The freq. magnitude scalers filter
-// const float * restrict W,//The windowing function
-// fftwf_complex * restrict output_window,//The transformed window'd src
-// struct userdata *u){//Collection of constants
- //float_vector_t x = {X, X, X, X};
-// const size_t window_size = PA_ROUND_UP(u->window_size,v_size);
-// const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2);
-// //const size_t R = PA_ROUND_UP(u->R, v_size);
-// const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
-// overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
-//
-// //assert(u->samples_gathered >= u->R);
-// //zero out the bit beyond the real overlap so we don't add garbage
-// for(size_t j = overlap_size; j > u->overlap_size; --j){
-// overlap[j-1] = 0;
-// }
-// //use a linear-phase sliding STFT and overlap-add method
-// //zero padd the data
-// memset(dst + u->window_size, 0, (u->fft_size - u->window_size)*sizeof(float));
-// //window the data
-// for(size_t j = 0; j < window_size; j += v_size){
-// //dst[j] = W[j]*src[j];
-// float_vector_t *d = (float_vector_t*) (dst+j);
-// float_vector_t *w = (float_vector_t*) (W+j);
-// float_vector_t *s = (float_vector_t*) (src+j);
+//regardless of sse enabled, the loops in here assume
+//16 byte aligned addresses and memory allocations divisible by v_size
+static void dsp_logic(
+ float * restrict dst,//used as a temp array too, needs to be fft_length!
+ float * restrict src,/*input data w/ overlap at start,
+ *automatically cycled in routine
+ */
+ float * restrict overlap,//The size of the overlap
+ const float X,//multipliar
+ const float * restrict H,//The freq. magnitude scalers filter
+ const float * restrict W,//The windowing function
+ fftwf_complex * restrict output_window,//The transformed window'd src
+ struct userdata *u){//Collection of constants
+ const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
+
+
+ //assert(u->samples_gathered >= u->R);
+ //use a linear-phase sliding STFT and overlap-add method
+ for(size_t j = 0; j < u->window_size; j += v_size){
+ //dst[j] = W[j] * src[j];
+ float_vector_t *d = (float_vector_t*) (dst + j);
+ float_vector_t *w = (float_vector_t*) (W + j);
+ float_vector_t *s = (float_vector_t*) (src + j);
//#if __SSE2__
-// d->m = _mm_mul_ps(x->m, _mm_mul_ps(w->m, s->m));
+ d->m = _mm_mul_ps(w->m, s->m);
//#else
-// d->v = x->v * w->v * s->v;
+// d->v = w->v * s->v;
//#endif
-// }
-// //Processing is done here!
-// //do fft
-// fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
-//
-//
-// //perform filtering - purely magnitude based
-// for(size_t j = 0;j < fft_h; j+=v_size/2){
-// //output_window[j][0]*=H[j];
-// //output_window[j][1]*=H[j];
-// float_vector_t *d = (float_vector_t*)(output_window+j);
-// float_vector_t h;
-// h.f[0] = h.f[1] = H[j];
-// h.f[2] = h.f[3] = H[j+1];
+ }
+ //zero padd the the remaining fft window
+ memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
+
+ //Processing is done here!
+ //do fft
+ fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
+ //perform filtering - purely magnitude based
+ for(size_t j = 0; j < FILTER_SIZE; j += v_size / 2){
+ //output_window[j][0]*=H[j];
+ //output_window[j][1]*=H[j];
+ float_vector_t *d = (float_vector_t*)( ((float *) output_window) + 2 * j);
+ float_vector_t h;
+ h.f[0] = h.f[1] = H[j];
+ h.f[2] = h.f[3] = H[j + 1];
//#if __SSE2__
-// d->m = _mm_mul_ps(d->m, h.m);
+ d->m = _mm_mul_ps(d->m, h.m);
//#else
-// d->v = d->v*h->v;
+// d->v = d->v * h.v;
//#endif
-// }
-// //inverse fft
-// fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
-//
-// ////debug: tests overlaping add
-// ////and negates ALL PREVIOUS processing
-// ////yields a perfect reconstruction if COLA is held
-// //for(size_t j = 0; j < u->window_size; ++j){
-// // dst[j] = W[j]*src[j];
-// //}
-//
-// //overlap add and preserve overlap component from this window (linear phase)
-// for(size_t j = 0; j < overlap_size; j+=v_size){
-// //dst[j]+=overlap[j];
-// //overlap[j]+=dst[j+R];
-// float_vector_t *d = (float_vector_t*)(dst+j);
-// float_vector_t *o = (float_vector_t*)(overlap+j);
+ }
+
+ //inverse fft
+ fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
+
+ ////debug: tests overlaping add
+ ////and negates ALL PREVIOUS processing
+ ////yields a perfect reconstruction if COLA is held
+ //for(size_t j = 0; j < u->window_size; ++j){
+ // dst[j] = W[j] * src[j];
+ //}
+
+ //overlap add and preserve overlap component from this window (linear phase)
+ for(size_t j = 0; j < overlap_size; j += v_size){
+ //dst[j]+=overlap[j];
+ //overlap[j]+=dst[j+R];
+ float_vector_t *d = (float_vector_t*)(dst + j);
+ float_vector_t *o = (float_vector_t*)(overlap + j);
//#if __SSE2__
-// d->m = _mm_add_ps(d->m, o->m);
-// o->m = ((float_vector_t*)(dst+u->R+j))->m;
+ d->m = _mm_add_ps(d->m, o->m);
+ o->m = ((float_vector_t*)(dst + u->R + j))->m;
//#else
-// d->v = d->v+o->v;
-// o->v = ((float_vector_t*)(dst+u->R+j))->v;
+// d->v = d->v + o->v;
+// o->v = ((float_vector_t*)(dst + u->R + j))->v;
//#endif
-// }
-// //memcpy(overlap, dst+u->R, u->overlap_size*sizeof(float));
-//
-// //////debug: tests if basic buffering works
-// //////shouldn't modify the signal AT ALL (beyond roundoff)
-// //for(size_t j = 0; j < u->window_size; ++j){
-// // dst[j] = src[j];
-// //}
-//
-// //preseve the needed input for the next window's overlap
-// memmove(src, src + u->R,
-// u->overlap_size * sizeof(float)
-// );
-//}
+ }
+ //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
+ //zero out the bit beyond the real overlap so we don't add garbage next iteration
+ memset(overlap + u->overlap_size, 0, overlap_size - u->overlap_size);
+
+ ////debug: tests if basic buffering works
+ ////shouldn't modify the signal AT ALL (beyond roundoff)
+ //for(size_t j = 0; j < u->window_size; ++j){
+ // dst[j] = src[j];
+ //}
+
+ //preseve the needed input for the next window's overlap
+ memmove(src, src + u->R,
+ (u->samples_gathered - u->R) * sizeof(float)
+ );
+}
+#endif
static void process_samples(struct userdata *u, pa_memchunk *tchunk){
size_t fs = pa_frame_size(&(u->sink->sample_spec));
@@ -685,7 +677,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
//invalidate the output q
pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
pa_log("Resetting filter");
- reset_filter(u);
+ //reset_filter(u); //this is the "proper" thing to do...
}
}
@@ -1064,9 +1056,12 @@ int pa__init(pa_module*m) {
pa_modargs_get_value_boolean(ma, "set_default", &u->set_default);
u->channels = ss.channels;
- u->fft_size = pow(2, ceil(log(ss.rate)/log(2)));//probably unstable near corner cases of powers of 2
+ u->fft_size = pow(2, ceil(log(ss.rate) / log(2)));//probably unstable near corner cases of powers of 2
pa_log_debug("fft size: %ld", u->fft_size);
u->window_size = 15999;
+ if(u->window_size % 2 == 0){
+ u->window_size--;
+ }
u->R = (u->window_size + 1) / 2;
u->overlap_size = u->window_size - u->R;
u->samples_gathered = 0;
@@ -1090,7 +1085,6 @@ int pa__init(pa_module*m) {
u->a_H[c] = pa_aupdate_new();
u->input[c] = NULL;
u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float));
- memset(u->overlap_accum[c], 0, u->overlap_size*sizeof(float));
}
u->output_window = alloc((FILTER_SIZE), sizeof(fftwf_complex));
u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
commit d25b9eab0fff1040713cf297f40450e0f7641870
Author: Jason Newton <jason at archer.wyred.org>
Date: Mon Oct 19 18:28:25 2009 -0700
module-equalizer-sink: drop source executable permissions configure.ac: add enable/disable + summary line for fftw
diff --git a/configure.ac b/configure.ac
index 77ec884..b34821a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1513,6 +1513,11 @@ if test "x${HAVE_SIMPLEDB}" = "x1" ; then
ENABLE_SIMPLEDB=yes
fi
+ENABLE_FFTW=no
+if test "x${HAVE_FFTW}" = "x1" ; then
+ ENABLE_FFTW=yes
+fi
+
ENABLE_OPENSSL=no
if test "x${HAVE_OPENSSL}" = "x1" ; then
ENABLE_OPENSSL=yes
@@ -1563,6 +1568,7 @@ echo "
Enable tdb: ${ENABLE_TDB}
Enable gdbm: ${ENABLE_GDBM}
Enable simple database: ${ENABLE_SIMPLEDB}
+ Enable fftw: ${ENABLE_FFTW}
System User: ${PA_SYSTEM_USER}
System Group: ${PA_SYSTEM_GROUP}
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
old mode 100755
new mode 100644
commit 744490a681be7356efba4160bfb29a3e76e85888
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 21:29:01 2009 +0100
memblock: decrease tile size to 64k again
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index eac4a59..f38b17c 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
commit 4538523a2999ee36e19f3f09a8ca5328185f9a67
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:26:48 2009 +0100
libpulse: introduce pa_context_get_tile_size() call
diff --git a/src/map-file b/src/map-file
index 6f7bdac..5011122 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 7468d0a..e33143d 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 ecff58d..6ac8ee5 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
commit 7c55d6e91d21971e187bf9602dce38cb49666cc4
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:27:14 2009 +0100
clients: drop definition of BUFSIZE which is unused
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 141ab5b..51de120 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;
diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
index c327ee4..534b77b 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;
commit 8678f565322ccc1bfbaa0f21024f7255ed58b933
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:27:50 2009 +0100
pactl: include information about client context in pactl stat output
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 51de120..7ef02ec 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -156,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"
commit 78984e439553f5e6eeb97c90ec1df9141fbe91d8
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:28:12 2009 +0100
pactl: format cookie a little bit nicer
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 7ef02ec..ee67c42 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -180,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,
@@ -189,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();
}
commit 27c6a80ccb9ccfdd00524360938599cf2d14d4b6
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:47:21 2009 +0100
protocol-native: declare that user configured volumes are always absolute
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index d06dd4e..b7471c0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1047,8 +1047,10 @@ static playback_stream* playback_stream_new(
data.sink = sink;
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);
+ data.volume_is_absolute = TRUE;
+ }
if (muted_set)
pa_sink_input_new_data_set_muted(&data, muted);
data.sync_base = ssync ? ssync->sink_input : NULL;
commit 2501687579e359d5032a4d165b2ffc8f5b1b8ba6
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:47:50 2009 +0100
libpulse: explain semantics of pa_stream_connect_playback() in more detail
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 2e8e71a..bc54a11 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 */ ,
commit 546bcf3f2f9711f0d08c21c3b775994844e7e2a2
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Oct 28 23:50:42 2009 +0100
protocol-native: if a client set volume/mute/device store it since it is user input
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index b7471c0..010420e 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1044,15 +1044,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) {
pa_sink_input_new_data_set_volume(&data, volume);
data.volume_is_absolute = TRUE;
+ data.save_volume = TRUE;
}
- if (muted_set)
+ 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;
commit f27a50691c8fe45bac7dd6b21fac91a359def3a1
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Oct 29 00:46:22 2009 +0100
libpulse: introduce PA_STREAM_RELATIVE_VOLUME
diff --git a/PROTOCOL b/PROTOCOL
index 92cc283..883b8bb 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -188,3 +188,9 @@ new messages:
PA_COMMAND_SET_SINK_PORT
PA_COMMAND_SET_SOURCE_PORT
+
+## v17, implemented by >= 0.9.20
+
+new flag at end of CREATE_PLAYBACK_STREAM:
+
+ bool relative_volume
diff --git a/configure.ac b/configure.ac
index b34821a..d7f55ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,7 +40,7 @@ AC_SUBST(PA_MAJORMINORMICRO, pa_major.pa_minor.pa_micro)
AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/])
AC_SUBST(PA_API_VERSION, 12)
-AC_SUBST(PA_PROTOCOL_VERSION, 16)
+AC_SUBST(PA_PROTOCOL_VERSION, 17)
# The stable ABI for client applications, for the version info x:y:z
# always will hold y=z
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 5d0a0b4..30a076d 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 2bc2b1e..2997962 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/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 010420e..bb29a19 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;
@@ -1052,7 +1053,7 @@ static playback_stream* playback_stream_new(
pa_sink_input_new_data_set_channel_map(&data, map);
if (volume) {
pa_sink_input_new_data_set_volume(&data, volume);
- data.volume_is_absolute = TRUE;
+ data.volume_is_absolute = !relative_volume;
data.save_volume = TRUE;
}
if (muted_set) {
@@ -1846,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;
@@ -1939,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);
@@ -1978,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);
commit 2edb4df175ee69e386ec3923e69af6899f55e2eb
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Oct 29 01:49:40 2009 +0100
smoother: add comments about optimization recommendations from Jason Newton
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index d6c3787..1371ad5 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;
commit e7e4e4459e6dad888d1f9a01d0b185221e1a120e
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Oct 29 01:52:39 2009 +0100
simd: update test cases
diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c
index 745c7de..5bf72ed 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 1cc4e0a..620524f 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__) */
commit 754644fa6e1ec83dba85bf586a2b09c2283aa096
Merge: e7e4e44 e9ccc61
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Oct 29 01:54:45 2009 +0100
Merge remote branch 'origin/master'
--
hooks/post-receive
PulseAudio Sound Server
More information about the pulseaudio-commits
mailing list