98
92
"source-output-index") != NULL);
101
typedef void (*OperationFunc) (EmpathyGstAudioSrc *, GSimpleAsyncResult *);
106
GSimpleAsyncResult *result;
110
operation_new (OperationFunc func,
111
GSimpleAsyncResult *result)
113
Operation *o = g_slice_new0 (Operation);
122
operation_free (Operation *o,
127
g_simple_async_result_set_error (o->result,
128
G_IO_ERROR, G_IO_ERROR_CANCELLED,
129
"The audio source was disposed");
130
g_simple_async_result_complete (o->result);
131
g_object_unref (o->result);
134
g_slice_free (Operation, o);
138
operation_get_microphones_free (gpointer data)
140
GQueue *queue = data;
143
for (l = queue->head; l != NULL; l = l->next)
145
EmpathyAudioSrcMicrophone *mic = l->data;
148
g_free (mic->description);
149
g_slice_free (EmpathyAudioSrcMicrophone, mic);
152
g_queue_free (queue);
156
operation_get_microphones_cb (pa_context *context,
157
const pa_source_info *info,
161
GSimpleAsyncResult *result = userdata;
162
EmpathyAudioSrcMicrophone *mic;
167
g_simple_async_result_complete (result);
168
g_object_unref (result);
96
empathy_audio_src_microphone_changed_cb (EmpathyMicMonitor *monitor,
97
guint source_output_idx,
101
EmpathyGstAudioSrc *self = user_data;
102
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
103
guint audio_src_idx = PA_INVALID_INDEX;
105
g_object_get (priv->src, "source-output-index", &audio_src_idx, NULL);
107
if (source_output_idx == PA_INVALID_INDEX
108
|| source_output_idx != audio_src_idx)
111
if (priv->source_idx == source_idx)
114
priv->source_idx = source_idx;
115
g_object_notify (G_OBJECT (self), "microphone");
119
empathy_audio_src_get_current_mic_cb (GObject *source_object,
120
GAsyncResult *result,
123
EmpathyMicMonitor *monitor = EMPATHY_MIC_MONITOR (source_object);
124
EmpathyGstAudioSrc *self = user_data;
125
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
127
GError *error = NULL;
129
source_idx = empathy_mic_monitor_get_current_mic_finish (monitor, result, &error);
133
DEBUG ("Failed to get current mic: %s", error->message);
134
g_clear_error (&error);
172
mic = g_slice_new0 (EmpathyAudioSrcMicrophone);
173
mic->index = info->index;
174
mic->name = g_strdup (info->name);
175
mic->description = g_strdup (info->description);
176
mic->is_monitor = (info->monitor_of_sink != PA_INVALID_INDEX);
178
/* add it to the queue */
179
queue = g_simple_async_result_get_op_res_gpointer (result);
180
g_queue_push_tail (queue, mic);
184
operation_get_microphones (EmpathyGstAudioSrc *self,
185
GSimpleAsyncResult *result)
187
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
189
g_assert_cmpuint (pa_context_get_state (priv->context), ==, PA_CONTEXT_READY);
191
g_simple_async_result_set_op_res_gpointer (result, g_queue_new (),
192
operation_get_microphones_free);
194
pa_context_get_source_info_list (priv->context,
195
operation_get_microphones_cb, result);
199
operation_change_microphone_cb (pa_context *context,
203
GSimpleAsyncResult *result = userdata;
207
g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
208
"Failed to change microphone. Reason unknown.");
211
g_simple_async_result_complete (result);
212
g_object_unref (result);
216
operation_change_microphone (EmpathyGstAudioSrc *self,
217
GSimpleAsyncResult *result)
219
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
220
guint source_output_idx, microphone;
222
g_object_get (priv->src, "source-output-index", &source_output_idx, NULL);
224
g_assert_cmpuint (pa_context_get_state (priv->context), ==, PA_CONTEXT_READY);
225
g_assert_cmpuint (source_output_idx, !=, PA_INVALID_INDEX);
227
microphone = GPOINTER_TO_UINT (
228
g_simple_async_result_get_op_res_gpointer (result));
230
pa_context_move_source_output_by_index (priv->context, source_output_idx, microphone,
231
operation_change_microphone_cb, result);
235
operations_run (EmpathyGstAudioSrc *self)
237
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
238
pa_context_state_t state = pa_context_get_state (priv->context);
241
if (state != PA_CONTEXT_READY)
244
for (l = priv->operations->head; l != NULL; l = l->next)
246
Operation *o = l->data;
248
o->func (self, o->result);
250
operation_free (o, FALSE);
253
g_queue_clear (priv->operations);
257
empathy_audio_src_source_output_info_cb (pa_context *context,
258
const pa_source_output_info *info,
262
EmpathyGstAudioSrc *self = userdata;
263
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
268
/* There should only be one call here. */
270
if (priv->source_idx == info->source)
273
priv->source_idx = info->source;
138
if (priv->source_idx == source_idx)
141
priv->source_idx = source_idx;
274
142
g_object_notify (G_OBJECT (self), "microphone");
278
empathy_audio_src_source_info_cb (pa_context *context,
279
const pa_source_info *info,
283
EmpathyGstAudioSrc *self = userdata;
289
is_monitor = (info->monitor_of_sink != PA_INVALID_INDEX);
291
g_signal_emit (self, signals[MICROPHONE_ADDED], 0,
292
info->index, info->name, info->description, is_monitor);
296
empathy_audio_src_pa_event_cb (pa_context *context,
297
pa_subscription_event_type_t type,
301
EmpathyGstAudioSrc *self = userdata;
302
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
304
if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
305
&& (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE
306
&& idx == priv->source_output_idx)
308
/* Microphone in the source output has changed */
309
pa_context_get_source_output_info (context, idx,
310
empathy_audio_src_source_output_info_cb, self);
312
else if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE
313
&& (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
315
/* A mic has been removed */
316
g_signal_emit (self, signals[MICROPHONE_REMOVED], 0, idx);
318
else if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE
319
&& (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW)
321
/* A mic has been plugged in */
322
pa_context_get_source_info_by_index (context, idx,
323
empathy_audio_src_source_info_cb, self);
328
empathy_audio_src_pa_subscribe_cb (pa_context *context,
333
DEBUG ("Failed to subscribe to PulseAudio events");
337
empathy_audio_src_pa_state_change_cb (pa_context *context,
340
EmpathyGstAudioSrc *self = userdata;
341
EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
342
pa_context_state_t state = pa_context_get_state (priv->context);
344
if (state == PA_CONTEXT_READY)
346
/* Listen to pulseaudio events so we know when sources are
347
* added and when the microphone is changed. */
348
pa_context_set_subscribe_callback (priv->context,
349
empathy_audio_src_pa_event_cb, self);
350
pa_context_subscribe (priv->context,
351
PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT,
352
empathy_audio_src_pa_subscribe_cb, NULL);
354
operations_run (self);
359
146
empathy_audio_src_source_output_index_notify (GObject *object,
360
147
GParamSpec *pspec,
361
148
EmpathyGstAudioSrc *self)