summaryrefslogtreecommitdiff
path: root/src/audio_out/audio_pulse_out.c
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2010-09-23 18:19:29 +0100
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2010-09-23 18:19:29 +0100
commit81e0d9f0ddaa5465cf8f9ec5ca2aad7df8d3b4ab (patch)
treef6c25b308dfd61acb8e5cd687a68f2f580d28ec6 /src/audio_out/audio_pulse_out.c
parent486fe1fc46d5f5a87696488184de7b7a5a9cb857 (diff)
parent4100ae40f29ee52181e927a8976b04614f6e1620 (diff)
downloadxine-lib-81e0d9f0ddaa5465cf8f9ec5ca2aad7df8d3b4ab.tar.gz
xine-lib-81e0d9f0ddaa5465cf8f9ec5ca2aad7df8d3b4ab.tar.bz2
Merge from 1.1.
Diffstat (limited to 'src/audio_out/audio_pulse_out.c')
-rw-r--r--src/audio_out/audio_pulse_out.c113
1 files changed, 89 insertions, 24 deletions
diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c
index 78ff82028..bd057501b 100644
--- a/src/audio_out/audio_pulse_out.c
+++ b/src/audio_out/audio_pulse_out.c
@@ -202,7 +202,8 @@ static void __xine_pa_context_success_callback(pa_context *c, int success, void
* instance.
*
* This function saves the volume field of the passed structure to the
- * @c cvolume variable of the output instance.
+ * @c cvolume variable of the output instance and send an update volume
+ * event to the frontend.
*/
static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info *info,
int is_last, void *userdata) {
@@ -226,6 +227,66 @@ static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info
#else
this->muted = pa_cvolume_is_muted (&this->cvolume);
#endif
+
+ /* send update volume event to frontend */
+
+ xine_event_t event;
+ xine_audio_level_data_t data;
+ xine_stream_t *stream;
+ xine_list_iterator_t ite;
+
+ data.right = data.left = (int) (pa_sw_volume_to_linear(this->swvolume)*100);
+
+ data.mute = this->muted;
+
+ event.type = XINE_EVENT_AUDIO_LEVEL;
+ event.data = &data;
+ event.data_length = sizeof(data);
+
+ pthread_mutex_lock(&this->xine->streams_lock);
+ for(ite = xine_list_front(this->xine->streams); ite; ite =
+ xine_list_next(this->xine->streams, ite)) {
+ stream = xine_list_get_value(this->xine->streams, ite);
+ event.stream = stream;
+ xine_event_send(stream, &event);
+ }
+ pthread_mutex_unlock(&this->xine->streams_lock);
+}
+
+/**
+ * @brief Callback function called when the state of the daemon changes
+ * @param c Context in which the state of the daemon changes
+ * @param t Subscription event type
+ * @param idx Index of the sink
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_context_subscribe_callback(pa_context *c,
+ pa_subscription_event_type_t t, uint32_t idx, void *this_gen)
+{
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+ int index;
+
+ if (this->stream == NULL)
+ return;
+
+ index = pa_stream_get_index(this->stream);
+
+ if (index != idx)
+ return;
+
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
+ return;
+
+ pa_operation *operation = pa_context_get_sink_input_info(
+ this->context, index, __xine_pa_sink_info_callback, this);
+
+ if (operation == NULL) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to get sink info: %s\n", pa_strerror(pa_context_errno (this->context)));
+ return;
+ }
+
+ pa_operation_unref(operation);
}
static int connect_context(pulse_driver_t *this) {
@@ -248,6 +309,10 @@ static int connect_context(pulse_driver_t *this) {
_x_assert(this->context);
pa_context_set_state_callback(this->context, __xine_pa_context_state_callback, this);
+
+ /* set subscribe callback (for volume change information) */
+
+ pa_context_set_subscribe_callback(this->context, __xine_pa_context_subscribe_callback, this);
}
if (pa_context_get_state(this->context) == PA_CONTEXT_UNCONNECTED) {
@@ -272,6 +337,17 @@ static int connect_context(pulse_driver_t *this) {
pa_threaded_mainloop_wait(this->mainloop);
}
+ /* subscribe to sink input events (for volume change information) */
+
+ pa_operation *operation = pa_context_subscribe(this->context,
+ PA_SUBSCRIPTION_MASK_SINK_INPUT,
+ __xine_pa_context_success_callback, this);
+
+ if (operation == NULL) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to enable event notification: %s\n", pa_strerror(pa_context_errno(this->context)));
+ return -1;
+ }
+
return 0;
}
@@ -433,34 +509,23 @@ static int ao_pulse_open(ao_driver_t *this_gen,
entry = cfg->lookup_entry (cfg, "audio.volume.mixer_volume");
if (entry) {
this->ao_driver.set_property(&this->ao_driver, AO_PROP_MIXER_VOL, entry->num_value);
-
- /* Notify frontend about the volume change */
- xine_event_t event;
- xine_audio_level_data_t data;
- xine_stream_t *stream;
- xine_list_iterator_t ite;
-
- data.right = data.left = entry->num_value;
- data.mute = 0;
-
- event.type = XINE_EVENT_AUDIO_LEVEL;
- event.data = &data;
- event.data_length = sizeof(data);
-
- pthread_mutex_lock(&this->xine->streams_lock);
- for(ite = xine_list_front(this->xine->streams); ite; ite =
- xine_list_next(this->xine->streams, ite)) {
- stream = xine_list_get_value(this->xine->streams, ite);
- event.stream = stream;
- xine_event_send(stream, &event);
- }
- pthread_mutex_unlock(&this->xine->streams_lock);
-
}
}
+ }
+
+ /* get pa sink input information to trigger a update volume event in the frontend */
+
+ pa_operation *operation = pa_context_get_sink_input_info(
+ this->context, pa_stream_get_index(this->stream),
+ __xine_pa_sink_info_callback, this);
+ if (operation == NULL) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to get sink info: %s\n", pa_strerror(pa_context_errno (this->context)));
+ goto fail;
}
+ pa_operation_unref(operation);
+
return this->sample_rate;
fail: