diff options
Diffstat (limited to 'src/pulse')
-rw-r--r-- | src/pulse/channelmap.c | 57 | ||||
-rw-r--r-- | src/pulse/channelmap.h | 5 | ||||
-rw-r--r-- | src/pulse/def.h | 9 | ||||
-rw-r--r-- | src/pulse/error.c | 4 | ||||
-rw-r--r-- | src/pulse/proplist.h | 4 | ||||
-rw-r--r-- | src/pulse/stream.c | 8 | ||||
-rw-r--r-- | src/pulse/stream.h | 2 | ||||
-rw-r--r-- | src/pulse/volume.c | 120 | ||||
-rw-r--r-- | src/pulse/volume.h | 19 |
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 */ |