summaryrefslogtreecommitdiffstats
path: root/src/pulse
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulse')
-rw-r--r--src/pulse/channelmap.c57
-rw-r--r--src/pulse/channelmap.h5
-rw-r--r--src/pulse/def.h9
-rw-r--r--src/pulse/error.c4
-rw-r--r--src/pulse/proplist.h4
-rw-r--r--src/pulse/stream.c8
-rw-r--r--src/pulse/stream.h2
-rw-r--r--src/pulse/volume.c120
-rw-r--r--src/pulse/volume.h19
9 files changed, 211 insertions, 17 deletions
diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index 455bda1b..6ff30c26 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -647,30 +647,77 @@ int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
int pa_channel_map_can_balance(const pa_channel_map *map) {
unsigned c;
+ pa_bool_t left = FALSE, right = FALSE;
pa_assert(map);
- for (c = 0; c < map->channels; c++)
+ for (c = 0; c < map->channels; c++) {
switch (map->map[c]) {
case PA_CHANNEL_POSITION_LEFT:
- case PA_CHANNEL_POSITION_RIGHT:
case PA_CHANNEL_POSITION_REAR_LEFT:
- case PA_CHANNEL_POSITION_REAR_RIGHT:
case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
- case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
case PA_CHANNEL_POSITION_SIDE_LEFT:
+ case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
+ case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
+ left = TRUE;
+ break;
+
+ case PA_CHANNEL_POSITION_RIGHT:
+ case PA_CHANNEL_POSITION_REAR_RIGHT:
+ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
case PA_CHANNEL_POSITION_SIDE_RIGHT:
+ case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
+ case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
+ right = TRUE;
+ break;
+
+ default:
+ ;
+ }
+
+ if (left && right)
+ return 1;
+ }
+
+ return 0;
+}
+
+int pa_channel_map_can_fade(const pa_channel_map *map) {
+ unsigned c;
+ pa_bool_t front = FALSE, rear = FALSE;
+
+ for (c = 0; c < map->channels; c++) {
+
+ switch (map->map[c]) {
+ case PA_CHANNEL_POSITION_FRONT_LEFT:
+ case PA_CHANNEL_POSITION_FRONT_RIGHT:
+ case PA_CHANNEL_POSITION_FRONT_CENTER:
+ case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
+ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
+ case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:
+ front = TRUE;
+ break;
+
+ case PA_CHANNEL_POSITION_REAR_LEFT:
+ case PA_CHANNEL_POSITION_REAR_RIGHT:
+ case PA_CHANNEL_POSITION_REAR_CENTER:
case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
- return 1;
+ case PA_CHANNEL_POSITION_TOP_REAR_CENTER:
+ rear = TRUE;
+ break;
default:
;
}
+ if (front && rear)
+ return 1;
+ }
+
return 0;
}
diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index de2d712a..f9124b2e 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -239,6 +239,11 @@ int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) PA
* available. \since 0.9.15 */
int pa_channel_map_can_balance(const pa_channel_map *map) PA_GCC_PURE;
+/** Returns non-zero if it makes sense to apply a volume 'fade'
+ * (i.e. 'balance' between front and rear) with this mapping, i.e. if
+ * there are front/rear channels available. \since 0.9.15 */
+int pa_channel_map_can_fade(const pa_channel_map *map) PA_GCC_PURE;
+
/** Tries to find a well-known channel mapping name for this channel
* mapping. I.e. "stereo", "surround-71" and so on. If the channel
* mapping is unknown NULL will be returned. This name can be parsed
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 7517a7aa..1acf19a0 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -237,12 +237,17 @@ typedef enum pa_stream_flags {
* checked whether the device this stream is connected to should
* auto-suspend. \since 0.9.15 */
- PA_STREAM_START_UNMUTED = 0x10000U
+ PA_STREAM_START_UNMUTED = 0x10000U,
/**< Create in unmuted state. If neither PA_STREAM_START_UNMUTED
* nor PA_STREAM_START_MUTED it is left to the server to decide
* whether to create the stream in muted or in unmuted
* state. \since 0.9.15 */
+ 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_flags_t;
/** \cond fulldocs */
@@ -268,6 +273,7 @@ typedef enum pa_stream_flags {
#define PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS
#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
/** \endcond */
@@ -358,6 +364,7 @@ enum {
PA_ERR_UNKNOWN, /**< The error code was unknown to the client */
PA_ERR_NOEXTENSION, /**< Extension does not exist. \since 0.9.12 */
PA_ERR_OBSOLETE, /**< Obsolete functionality. \since 0.9.15 */
+ PA_ERR_NOTIMPLEMENTED, /**< Missing implementation. \since 0.9.15 */
PA_ERR_MAX /**< Not really an error but the first invalid error code */
};
diff --git a/src/pulse/error.c b/src/pulse/error.c
index d9d0a8c6..d37084bb 100644
--- a/src/pulse/error.c
+++ b/src/pulse/error.c
@@ -61,7 +61,9 @@ const char*pa_strerror(int error) {
[PA_ERR_TOOLARGE] = N_("Too large"),
[PA_ERR_NOTSUPPORTED] = N_("Not supported"),
[PA_ERR_UNKNOWN] = N_("Unknown error code"),
- [PA_ERR_NOEXTENSION] = N_("No such extension")
+ [PA_ERR_NOEXTENSION] = N_("No such extension"),
+ [PA_ERR_OBSOLETE] = N_("Obsolete functionality"),
+ [PA_ERR_NOTIMPLEMENTED] = N_("Missing implementation")
};
pa_init_i18n();
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 203a28c5..990ffd19 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -65,6 +65,7 @@ PA_C_DECL_BEGIN
* application.process.binary
* application.process.user
* application.process.host
+ * application.process.machine_id D-Bus machine ID
* device.string
* device.api oss, alsa, sunaudio
* device.description
@@ -72,7 +73,7 @@ PA_C_DECL_BEGIN
* device.serial
* device.vendor_product_id
* device.class sound, modem, monitor, filter, abstract
- * device.form_factor laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset
+ * device.form_factor laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset, headphones, hands-free, car, hifi, computer, portable
* device.connector isa, pci, usb, firewire, bluetooth
* device.access_mode mmap, mmap_rewrite, serial
* device.master_device
@@ -114,6 +115,7 @@ PA_C_DECL_BEGIN
#define PA_PROP_APPLICATION_PROCESS_BINARY "application.process.binary"
#define PA_PROP_APPLICATION_PROCESS_USER "application.process.user"
#define PA_PROP_APPLICATION_PROCESS_HOST "application.process.host"
+#define PA_PROP_APPLICATION_PROCESS_MACHINE_ID "application.process.machine_id"
#define PA_PROP_DEVICE_STRING "device.string"
#define PA_PROP_DEVICE_API "device.api"
#define PA_PROP_DEVICE_DESCRIPTION "device.description"
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 5a29bd63..fe2514d9 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -877,7 +877,7 @@ static int create_stream(
PA_CHECK_VALIDITY(s->context, s->direct_on_input == PA_INVALID_INDEX || direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|
PA_STREAM_INTERPOLATE_TIMING|
- PA_STREAM_NOT_MONOTONOUS|
+ PA_STREAM_NOT_MONOTONIC|
PA_STREAM_AUTO_TIMING_UPDATE|
PA_STREAM_NO_REMAP_CHANNELS|
PA_STREAM_NO_REMIX_CHANNELS|
@@ -891,7 +891,8 @@ static int create_stream(
PA_STREAM_ADJUST_LATENCY|
PA_STREAM_EARLY_REQUESTS|
PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|
- PA_STREAM_START_UNMUTED)), PA_ERR_INVALID);
+ PA_STREAM_START_UNMUTED|
+ PA_STREAM_FAIL_ON_SUSPEND)), 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);
@@ -1017,6 +1018,7 @@ static int create_stream(
pa_tagstruct_put_boolean(t, flags & (PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED));
pa_tagstruct_put_boolean(t, flags & PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND);
+ pa_tagstruct_put_boolean(t, flags & PA_STREAM_FAIL_ON_SUSPEND);
}
pa_pstream_send_tagstruct(s->context->pstream, t);
@@ -1902,7 +1904,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
usec = calc_time(s, FALSE);
/* Make sure the time runs monotonically */
- if (!(s->flags & PA_STREAM_NOT_MONOTONOUS)) {
+ if (!(s->flags & PA_STREAM_NOT_MONOTONIC)) {
if (usec < s->previous_time)
usec = s->previous_time;
else
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 6cb363c8..1bec1ebf 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -532,7 +532,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
* value returned by this function is guaranteed to increase
* monotonically. (that means: the returned value is always greater or
* equal to the value returned on the last call) This behaviour can
- * be disabled by using PA_STREAM_NOT_MONOTONOUS. This may be
+ * be disabled by using PA_STREAM_NOT_MONOTONIC. This may be
* desirable to deal better with bad estimations of transport
* latencies, but may have strange effects if the application is not
* able to deal with time going 'backwards'. */
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 3434cb18..ba2ee8fb 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -337,10 +337,35 @@ static pa_bool_t on_center(pa_channel_position_t p) {
}
static pa_bool_t on_lfe(pa_channel_position_t p) {
+
return
p == PA_CHANNEL_POSITION_LFE;
}
+static pa_bool_t on_front(pa_channel_position_t p) {
+
+ return
+ p == PA_CHANNEL_POSITION_FRONT_LEFT ||
+ p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
+ p == PA_CHANNEL_POSITION_FRONT_CENTER ||
+ p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
+ p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
+}
+
+static pa_bool_t on_rear(pa_channel_position_t p) {
+
+ return
+ p == PA_CHANNEL_POSITION_REAR_LEFT ||
+ p == PA_CHANNEL_POSITION_REAR_RIGHT ||
+ p == PA_CHANNEL_POSITION_REAR_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_LEFT ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
+}
+
pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to) {
int a, b;
pa_cvolume result;
@@ -487,12 +512,12 @@ pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, flo
for (c = 0; c < map->channels; c++) {
if (on_left(map->map[c])) {
if (left == 0)
- v->values[c] = 0;
+ v->values[c] = nleft;
else
v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nleft) / (uint64_t) left);
} else if (on_right(map->map[c])) {
if (right == 0)
- v->values[c] = 0;
+ v->values[c] = nright;
else
v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nright) / (uint64_t) right);
}
@@ -505,7 +530,7 @@ pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
unsigned c;
pa_volume_t t = 0;
- pa_assert(c);
+ pa_assert(v);
for (c = 0; c < v->channels; c++)
if (v->values[c] > t)
@@ -519,3 +544,92 @@ pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
return v;
}
+
+static void get_avg_fr(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *f, pa_volume_t *r) {
+ int c;
+ pa_volume_t front = 0, rear = 0;
+ unsigned n_front = 0, n_rear = 0;
+
+ pa_assert(v);
+ pa_assert(map);
+ pa_assert(map->channels == v->channels);
+ pa_assert(f);
+ pa_assert(r);
+
+ for (c = 0; c < map->channels; c++) {
+ if (on_front(map->map[c])) {
+ front += v->values[c];
+ n_front++;
+ } else if (on_rear(map->map[c])) {
+ rear += v->values[c];
+ n_rear++;
+ }
+ }
+
+ if (n_front <= 0)
+ *f = PA_VOLUME_NORM;
+ else
+ *f = front / n_front;
+
+ if (n_rear <= 0)
+ *r = PA_VOLUME_NORM;
+ else
+ *r = rear / n_rear;
+}
+
+float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
+ pa_volume_t front, rear;
+
+ pa_assert(v);
+ pa_assert(map);
+ pa_assert(map->channels == v->channels);
+
+ get_avg_fr(map, v, &front, &rear);
+
+ if (front == rear)
+ return 0.0f;
+
+ if (rear > front)
+ return -1.0f + ((float) front / (float) rear);
+ else
+ return 1.0f - ((float) rear / (float) front);
+}
+
+pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade) {
+ pa_volume_t front, nfront, rear, nrear, m;
+ unsigned c;
+
+ pa_assert(map->channels == v->channels);
+ pa_assert(map);
+ pa_assert(v);
+ pa_assert(new_fade >= -1.0f);
+ pa_assert(new_fade <= 1.0f);
+
+ get_avg_fr(map, v, &front, &rear);
+
+ m = PA_MAX(front, rear);
+
+ if (new_fade <= 0) {
+ nfront = (new_fade + 1.0f) * m;
+ nrear = m;
+ } else {
+ nrear = (1.0f - new_fade) * m;
+ nfront = m;
+ }
+
+ for (c = 0; c < map->channels; c++) {
+ if (on_front(map->map[c])) {
+ if (front == 0)
+ v->values[c] = nfront;
+ else
+ v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nfront) / (uint64_t) front);
+ } else if (on_rear(map->map[c])) {
+ if (rear == 0)
+ v->values[c] = nrear;
+ else
+ v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nrear) / (uint64_t) rear);
+ }
+ }
+
+ return v;
+}
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 9a883ca7..8eef467f 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -242,12 +242,27 @@ float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) PA_
/** Adjust the 'balance' value for the specified volume with the
* specified channel map. v will be modified in place and
* returned. The balance is a value between -1.0f and +1.0f. This
- * operation might not be reversable! Also, after this call
+ * operation might not be reversible! Also, after this call
* pa_cvolume_get_balance() is not guaranteed to actually return the
- * requested balance (e.g. when the input volume was zero anyway for
+ * requested balance value (e.g. when the input volume was zero anyway for
* all channels) \since 0.9.15 */
pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance);
+/** Calculate a 'fade' value (i.e. 'balance' between front and rear)
+ * for the specified volume with the specified channel map. The return
+ * value will range from -1.0f (rear) to +1.0f (left) \since
+ * 0.9.15 */
+float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) PA_GCC_PURE;
+
+/** Adjust the 'fade' value (i.e. 'balance' between front and rear)
+ * for the specified volume with the specified channel map. v will be
+ * modified in place and returned. The balance is a value between
+ * -1.0f and +1.0f. This operation might not be reversible! Also,
+ * after this call pa_cvolume_get_fade() is not guaranteed to
+ * actually return the requested fade value (e.g. when the input volume
+ * was zero anyway for all channels) \since 0.9.15 */
+pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade);
+
/** Scale the passed pa_cvolume structure so that the maximum volume
* of all channels equals max. The proportions between the channel
* volumes are kept. \since 0.9.15 */