From 6146181a2cbcbcd3e5b631a9517441fefb9c4fcc Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Tue, 26 Jul 2011 10:28:40 +0100 Subject: audio-src: use pulsesrc instead of gconfaudiosrc Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index a3416f2ea..b721773b9 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -100,7 +100,7 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) g_signal_connect (priv->notifier, "element-added", G_CALLBACK (empathy_audio_src_element_added_cb), obj); - priv->src = gst_element_factory_make ("gconfaudiosrc", NULL); + priv->src = gst_element_factory_make ("pulsesrc", NULL); gst_bin_add (GST_BIN (obj), priv->src); fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->src)); -- cgit v1.2.3 From 8a937c926c79f24fdb36574cb036c9fc09532f3f Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Tue, 26 Jul 2011 10:32:34 +0100 Subject: audio-src: allow changing the audio source element Better than nothing, right? Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index b721773b9..252e8aabe 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -92,6 +92,7 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) { EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (obj); GstPad *ghost, *src; + const gchar *src_element; priv->peak_level = -G_MAXDOUBLE; priv->lock = g_mutex_new (); @@ -100,7 +101,11 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) g_signal_connect (priv->notifier, "element-added", G_CALLBACK (empathy_audio_src_element_added_cb), obj); - priv->src = gst_element_factory_make ("pulsesrc", NULL); + src_element = g_getenv ("EMPATHY_AUDIO_SRC"); + if (src_element == NULL) + src_element = "pulsesrc"; + + priv->src = gst_element_factory_make (src_element, NULL); gst_bin_add (GST_BIN (obj), priv->src); fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->src)); -- cgit v1.2.3 From 65e9deccdb37c518ebfa766b7762ace338e9a027 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Tue, 26 Jul 2011 14:24:29 +0100 Subject: audio-src: remove the element-added stuff Now that we hard-code pulsesrc, this is unnecessary. Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 252e8aabe..8730de892 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -22,7 +22,6 @@ #include #include -#include #include "empathy-audio-src.h" G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN) @@ -52,7 +51,6 @@ struct _EmpathyGstAudioSrcPrivate GstElement *src; GstElement *volume; GstElement *level; - FsElementAddedNotifier *notifier; gdouble peak_level; gdouble rms_level; @@ -65,28 +63,6 @@ struct _EmpathyGstAudioSrcPrivate (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \ EmpathyGstAudioSrcPrivate)) -static void -empathy_audio_src_element_added_cb (FsElementAddedNotifier *notifier, - GstBin *bin, GstElement *element, EmpathyGstAudioSrc *self) -{ - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume")) - { - gdouble volume; - - volume = empathy_audio_src_get_volume (self); - empathy_audio_src_set_volume (self, 1.0); - - if (priv->volume != NULL) - g_object_unref (priv->volume); - priv->volume = g_object_ref (element); - - if (volume != 1.0) - empathy_audio_src_set_volume (self, volume); - } -} - static void empathy_audio_src_init (EmpathyGstAudioSrc *obj) { @@ -97,10 +73,6 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) priv->peak_level = -G_MAXDOUBLE; priv->lock = g_mutex_new (); - priv->notifier = fs_element_added_notifier_new (); - g_signal_connect (priv->notifier, "element-added", - G_CALLBACK (empathy_audio_src_element_added_cb), obj); - src_element = g_getenv ("EMPATHY_AUDIO_SRC"); if (src_element == NULL) src_element = "pulsesrc"; @@ -108,8 +80,6 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) priv->src = gst_element_factory_make (src_element, NULL); gst_bin_add (GST_BIN (obj), priv->src); - fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->src)); - priv->volume = gst_element_factory_make ("volume", NULL); g_object_ref (priv->volume); -- cgit v1.2.3 From 7212c6e568aab0c729c9334b0b7a82e7eb33597d Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Tue, 26 Jul 2011 14:27:33 +0100 Subject: audio-src: add API to query available microphones Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++ src/empathy-audio-src.h | 12 +++ 2 files changed, 209 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 8730de892..df346ea66 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -22,6 +22,11 @@ #include #include +#include +#include + +#include + #include "empathy-audio-src.h" G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN) @@ -52,6 +57,10 @@ struct _EmpathyGstAudioSrcPrivate GstElement *volume; GstElement *level; + pa_glib_mainloop *loop; + pa_context *context; + GQueue *operations; + gdouble peak_level; gdouble rms_level; @@ -63,6 +72,135 @@ struct _EmpathyGstAudioSrcPrivate (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \ EmpathyGstAudioSrcPrivate)) +typedef void (*OperationFunc) (EmpathyGstAudioSrc *, GSimpleAsyncResult *); + +typedef struct +{ + OperationFunc func; + GSimpleAsyncResult *result; +} Operation; + +static Operation * +operation_new (OperationFunc func, + GSimpleAsyncResult *result) +{ + Operation *o = g_slice_new0 (Operation); + + o->func = func; + o->result = result; + + return o; +} + +static void +operation_free (Operation *o, + gboolean cancelled) +{ + if (cancelled) + { + g_simple_async_result_set_error (o->result, + G_IO_ERROR, G_IO_ERROR_CANCELLED, + "The audio source was disposed"); + g_simple_async_result_complete (o->result); + g_object_unref (o->result); + } + + g_slice_free (Operation, o); +} + +static void +operation_get_microphones_free (gpointer data) +{ + GQueue *queue = data; + GList *l; + + for (l = queue->head; l != NULL; l = l->next) + { + EmpathyAudioSrcMicrophone *mic = l->data; + + g_free (mic->description); + g_slice_free (EmpathyAudioSrcMicrophone, mic); + } + + g_queue_free (queue); +} + +static void +operation_get_microphones_cb (pa_context *context, + const pa_source_info *info, + int eol, + void *userdata) +{ + GSimpleAsyncResult *result = userdata; + EmpathyAudioSrcMicrophone *mic; + GQueue *queue; + + if (eol) + { + g_simple_async_result_complete (result); + g_object_unref (result); + return; + } + + /* ignore monitors */ + if (info->monitor_of_sink != PA_INVALID_INDEX) + return; + + mic = g_slice_new0 (EmpathyAudioSrcMicrophone); + mic->index = info->index; + mic->description = g_strdup (info->description); + + /* add it to the queue */ + queue = g_simple_async_result_get_op_res_gpointer (result); + g_queue_push_tail (queue, mic); +} + +static void +operation_get_microphones (EmpathyGstAudioSrc *self, + GSimpleAsyncResult *result) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + g_assert_cmpuint (pa_context_get_state (priv->context), ==, PA_CONTEXT_READY); + + g_simple_async_result_set_op_res_gpointer (result, g_queue_new (), + operation_get_microphones_free); + + pa_context_get_source_info_list (priv->context, + operation_get_microphones_cb, result); +} + +static void +operations_run (EmpathyGstAudioSrc *self) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + pa_context_state_t state = pa_context_get_state (priv->context); + GList *l; + + if (state != PA_CONTEXT_READY) + return; + + for (l = priv->operations->head; l != NULL; l = l->next) + { + Operation *o = l->data; + + o->func (self, o->result); + + operation_free (o, FALSE); + } + + g_queue_clear (priv->operations); +} + +static void +empathy_audio_src_pa_state_change_cb (pa_context *c, + void *userdata) +{ + EmpathyGstAudioSrc *self = userdata; + + operations_run (self); +} + static void empathy_audio_src_init (EmpathyGstAudioSrc *obj) { @@ -96,6 +234,16 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) gst_element_add_pad (GST_ELEMENT (obj), ghost); gst_object_unref (G_OBJECT (src)); + + priv->loop = pa_glib_mainloop_new (NULL); + priv->context = pa_context_new (pa_glib_mainloop_get_api (priv->loop), + "EmpathyAudioSrc"); + + pa_context_set_state_callback (priv->context, + empathy_audio_src_pa_state_change_cb, obj); + pa_context_connect (priv->context, NULL, 0, NULL); + + priv->operations = g_queue_new (); } static void empathy_audio_src_dispose (GObject *object); @@ -217,6 +365,14 @@ empathy_audio_src_dispose (GObject *object) priv->idle_id = 0; + if (priv->context != NULL) + pa_context_unref (priv->context); + priv->context = NULL; + + if (priv->loop != NULL) + pa_glib_mainloop_free (priv->loop); + priv->loop = NULL; + /* release any references held by the object here */ if (G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose) @@ -232,6 +388,10 @@ empathy_audio_src_finalize (GObject *object) /* free any data held directly by the object here */ g_mutex_free (priv->lock); + g_queue_foreach (priv->operations, (GFunc) operation_free, + GUINT_TO_POINTER (TRUE)); + g_queue_free (priv->operations); + G_OBJECT_CLASS (empathy_audio_src_parent_class)->finalize (object); } @@ -359,4 +519,41 @@ empathy_audio_src_get_volume (EmpathyGstAudioSrc *src) return volume; } +void +empathy_audio_src_get_microphones_async (EmpathyGstAudioSrc *src, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); + Operation *operation; + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (src), callback, user_data, + empathy_audio_src_get_microphones_async); + + operation = operation_new (operation_get_microphones, simple); + g_queue_push_tail (priv->operations, operation); + + /* gogogogo */ + operations_run (src); +} + +const GList * +empathy_audio_src_get_microphones_finish (EmpathyGstAudioSrc *src, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + GQueue *queue; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (src), empathy_audio_src_get_microphones_async), + NULL); + + queue = g_simple_async_result_get_op_res_gpointer (simple); + return queue->head; +} diff --git a/src/empathy-audio-src.h b/src/empathy-audio-src.h index 4bca31b61..c5887237f 100644 --- a/src/empathy-audio-src.h +++ b/src/empathy-audio-src.h @@ -23,6 +23,7 @@ #include #include +#include G_BEGIN_DECLS @@ -61,6 +62,17 @@ GstElement *empathy_audio_src_new (void); void empathy_audio_src_set_volume (EmpathyGstAudioSrc *src, gdouble volume); gdouble empathy_audio_src_get_volume (EmpathyGstAudioSrc *src); +typedef struct +{ + guint index; + gchar *description; +} EmpathyAudioSrcMicrophone; + +void empathy_audio_src_get_microphones_async (EmpathyGstAudioSrc *src, + GAsyncReadyCallback callback, gpointer user_data); +const GList * empathy_audio_src_get_microphones_finish (EmpathyGstAudioSrc *src, + GAsyncResult *result, GError **error); + G_END_DECLS #endif /* #ifndef __EMPATHY_GST_AUDIO_SRC_H__*/ -- cgit v1.2.3 From 77712e75df674fb1f6fb58bd92a26ce75cf41787 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Tue, 26 Jul 2011 17:45:50 +0100 Subject: audio-src: add the source name to the microphone info struct Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 2 ++ src/empathy-audio-src.h | 1 + 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index df346ea66..086b0a189 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -118,6 +118,7 @@ operation_get_microphones_free (gpointer data) { EmpathyAudioSrcMicrophone *mic = l->data; + g_free (mic->name); g_free (mic->description); g_slice_free (EmpathyAudioSrcMicrophone, mic); } @@ -148,6 +149,7 @@ operation_get_microphones_cb (pa_context *context, mic = g_slice_new0 (EmpathyAudioSrcMicrophone); mic->index = info->index; + mic->name = g_strdup (info->name); mic->description = g_strdup (info->description); /* add it to the queue */ diff --git a/src/empathy-audio-src.h b/src/empathy-audio-src.h index c5887237f..298d59c7d 100644 --- a/src/empathy-audio-src.h +++ b/src/empathy-audio-src.h @@ -65,6 +65,7 @@ gdouble empathy_audio_src_get_volume (EmpathyGstAudioSrc *src); typedef struct { guint index; + gchar *name; gchar *description; } EmpathyAudioSrcMicrophone; -- cgit v1.2.3 From 2223a2eb1e505b857ad13a44bc888149dc3f0334 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 11:39:21 +0100 Subject: audio-src: add API for changing microphone Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ src/empathy-audio-src.h | 5 ++++ 2 files changed, 84 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 086b0a189..fee1e46cf 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -172,6 +172,42 @@ operation_get_microphones (EmpathyGstAudioSrc *self, operation_get_microphones_cb, result); } +static void +operation_change_microphone_cb (pa_context *context, + int success, + void *userdata) +{ + GSimpleAsyncResult *result = userdata; + + if (!success) + { + g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to change microphone. Reason unknown."); + } + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +static void +operation_change_microphone (EmpathyGstAudioSrc *self, + GSimpleAsyncResult *result) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + guint stream_idx, microphone; + + g_object_get (priv->src, "stream-index", &stream_idx, NULL); + + g_assert_cmpuint (pa_context_get_state (priv->context), ==, PA_CONTEXT_READY); + g_assert_cmpuint (stream_idx, !=, G_MAXUINT); + + microphone = GPOINTER_TO_UINT ( + g_simple_async_result_get_op_res_gpointer (result)); + + pa_context_move_source_output_by_index (priv->context, stream_idx, microphone, + operation_change_microphone_cb, result); +} + static void operations_run (EmpathyGstAudioSrc *self) { @@ -559,3 +595,46 @@ empathy_audio_src_get_microphones_finish (EmpathyGstAudioSrc *src, return queue->head; } +void +empathy_audio_src_change_microphone_async (EmpathyGstAudioSrc *src, + guint microphone, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); + guint stream_idx; + GSimpleAsyncResult *simple; + Operation *operation; + + simple = g_simple_async_result_new (G_OBJECT (src), callback, user_data, + empathy_audio_src_change_microphone_async); + + g_object_get (priv->src, "stream-index", &stream_idx, NULL); + + if (stream_idx == G_MAXUINT) + { + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + "pulsesrc is not yet PLAYING"); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + g_simple_async_result_set_op_res_gpointer (simple, + GUINT_TO_POINTER (microphone), NULL); + + operation = operation_new (operation_change_microphone, simple); + g_queue_push_tail (priv->operations, operation); + + /* gogogogo */ + operations_run (src); +} + +gboolean +empathy_audio_src_change_microphone_finish (EmpathyGstAudioSrc *src, + GAsyncResult *result, + GError **error) +{ + empathy_implement_finish_void (src, + empathy_audio_src_change_microphone_async); +} diff --git a/src/empathy-audio-src.h b/src/empathy-audio-src.h index 298d59c7d..c65f3696a 100644 --- a/src/empathy-audio-src.h +++ b/src/empathy-audio-src.h @@ -74,6 +74,11 @@ void empathy_audio_src_get_microphones_async (EmpathyGstAudioSrc *src, const GList * empathy_audio_src_get_microphones_finish (EmpathyGstAudioSrc *src, GAsyncResult *result, GError **error); +void empathy_audio_src_change_microphone_async (EmpathyGstAudioSrc *src, + guint microphone, GAsyncReadyCallback callback, gpointer user_data); +gboolean empathy_audio_src_change_microphone_finish (EmpathyGstAudioSrc *src, + GAsyncResult *result, GError **error); + G_END_DECLS #endif /* #ifndef __EMPATHY_GST_AUDIO_SRC_H__*/ -- cgit v1.2.3 From 1de1a894194a0fa355ef382783fa54f25ddca75c Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 11:54:52 +0100 Subject: audio-src: add API for getting the mic source ID Also listen out for changes in the source output ID (but that'll only happen if we go READY -> NULL -> READY again). Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ src/empathy-audio-src.h | 2 ++ 2 files changed, 70 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index fee1e46cf..96caae970 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -45,6 +45,7 @@ enum { PROP_VOLUME = 1, PROP_RMS_LEVEL, PROP_PEAK_LEVEL, + PROP_MICROPHONE, }; /* private structure */ @@ -61,6 +62,9 @@ struct _EmpathyGstAudioSrcPrivate pa_context *context; GQueue *operations; + guint source_output_idx; + guint source_idx; + gdouble peak_level; gdouble rms_level; @@ -239,6 +243,50 @@ empathy_audio_src_pa_state_change_cb (pa_context *c, operations_run (self); } +static void +empathy_audio_src_source_output_info_cb (pa_context *context, + const pa_source_output_info *info, + int eol, + void *userdata) +{ + EmpathyGstAudioSrc *self = userdata; + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + if (eol) + return; + + /* There should only be one call here. */ + + if (priv->source_idx == info->source) + return; + + priv->source_idx = info->source; + g_object_notify (G_OBJECT (self), "microphone"); +} + +static void +empathy_audio_src_stream_index_notify (GObject *object, + GParamSpec *pspec, + EmpathyGstAudioSrc *self) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + guint stream_idx = G_MAXUINT; + + g_object_get (priv->src, "stream-index", &stream_idx, NULL); + + if (stream_idx == G_MAXUINT) + return; + + if (priv->source_output_idx == stream_idx) + return; + + /* It's actually changed. */ + priv->source_output_idx = stream_idx; + + pa_context_get_source_output_info (priv->context, stream_idx, + empathy_audio_src_source_output_info_cb, self); +} + static void empathy_audio_src_init (EmpathyGstAudioSrc *obj) { @@ -281,6 +329,10 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) empathy_audio_src_pa_state_change_cb, obj); pa_context_connect (priv->context, NULL, 0, NULL); + g_signal_connect (priv->src, "notify::stream-index", + G_CALLBACK (empathy_audio_src_stream_index_notify), + obj); + priv->operations = g_queue_new (); } @@ -329,6 +381,9 @@ empathy_audio_src_get_property (GObject *object, g_value_set_double (value, priv->rms_level); g_mutex_unlock (priv->lock); break; + case PROP_MICROPHONE: + g_value_set_uint (value, priv->source_idx); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -364,6 +419,11 @@ empathy_audio_src_class_init (EmpathyGstAudioSrcClass G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_VOLUME, param_spec); + param_spec = g_param_spec_uint ("microphone", "microphone", "microphone", + 0, G_MAXUINT, G_MAXUINT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_MICROPHONE, param_spec); + signals[PEAK_LEVEL_CHANGED] = g_signal_new ("peak-level-changed", G_TYPE_FROM_CLASS (empathy_audio_src_class), G_SIGNAL_RUN_LAST, @@ -595,6 +655,14 @@ empathy_audio_src_get_microphones_finish (EmpathyGstAudioSrc *src, return queue->head; } +guint +empathy_audio_src_get_microphone (EmpathyGstAudioSrc *src) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); + + return priv->source_idx; +} + void empathy_audio_src_change_microphone_async (EmpathyGstAudioSrc *src, guint microphone, diff --git a/src/empathy-audio-src.h b/src/empathy-audio-src.h index c65f3696a..286a34f9a 100644 --- a/src/empathy-audio-src.h +++ b/src/empathy-audio-src.h @@ -74,6 +74,8 @@ void empathy_audio_src_get_microphones_async (EmpathyGstAudioSrc *src, const GList * empathy_audio_src_get_microphones_finish (EmpathyGstAudioSrc *src, GAsyncResult *result, GError **error); +guint empathy_audio_src_get_microphone (EmpathyGstAudioSrc *src); + void empathy_audio_src_change_microphone_async (EmpathyGstAudioSrc *src, guint microphone, GAsyncReadyCallback callback, gpointer user_data); gboolean empathy_audio_src_change_microphone_finish (EmpathyGstAudioSrc *src, -- cgit v1.2.3 From 01b0be54353820459d4741f2858be21207f7e754 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 13:21:49 +0100 Subject: audio-src: add some comments explaining the PA changes Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 96caae970..bde6e2942 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -321,14 +321,20 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) gst_object_unref (G_OBJECT (src)); + /* PulseAudio stuff: We need to create a dummy pa_glib_mainloop* so + * Pulse can use the mainloop that GTK has created for us. */ priv->loop = pa_glib_mainloop_new (NULL); priv->context = pa_context_new (pa_glib_mainloop_get_api (priv->loop), "EmpathyAudioSrc"); + /* Now listen for state changes so we know when we've connected. */ pa_context_set_state_callback (priv->context, empathy_audio_src_pa_state_change_cb, obj); pa_context_connect (priv->context, NULL, 0, NULL); + /* Listen to changes to GstPulseSrc:stream-index so we know when + * it's no longer G_MAXUINT (starting for the first time) or if it + * changes (READY->NULL->READY...) */ g_signal_connect (priv->src, "notify::stream-index", G_CALLBACK (empathy_audio_src_stream_index_notify), obj); -- cgit v1.2.3 From 204fa9e744560be4bc0fbafbc5af95a3cf6b3a12 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 17:24:58 +0100 Subject: src: give empathy-call sources to the marshal generator Signed-off-by: Jonny Lamb --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 2a34494eb..e6574077d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -262,10 +262,10 @@ dist_man_MANS = \ empathy.1 \ empathy-accounts.1 -src-marshal.list: $(empathy_SOURCES) Makefile.am +src-marshal.list: $(empathy_SOURCES) $(empathy_call_SOURCES) Makefile.am $(AM_V_GEN)( cd $(srcdir) && \ sed -n -e 's/.*src_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ - $(empathy_SOURCES) $(empathy_av_SOURCES) ) \ + $(empathy_SOURCES) $(empathy_av_SOURCES) $(empathy_call_SOURCES) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ -- cgit v1.2.3 From d9c603695a6c04b2eae543e9339014873ac18812 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 17:44:21 +0100 Subject: audio-src: listen to PA state changes and signal accordingly Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 118 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index bde6e2942..d44298fd8 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -29,6 +29,8 @@ #include "empathy-audio-src.h" +#include "src-marshal.h" + G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN) /* signal enum */ @@ -36,6 +38,8 @@ enum { PEAK_LEVEL_CHANGED, RMS_LEVEL_CHANGED, + MICROPHONE_ADDED, + MICROPHONE_REMOVED, LAST_SIGNAL }; @@ -234,15 +238,6 @@ operations_run (EmpathyGstAudioSrc *self) g_queue_clear (priv->operations); } -static void -empathy_audio_src_pa_state_change_cb (pa_context *c, - void *userdata) -{ - EmpathyGstAudioSrc *self = userdata; - - operations_run (self); -} - static void empathy_audio_src_source_output_info_cb (pa_context *context, const pa_source_output_info *info, @@ -264,6 +259,84 @@ empathy_audio_src_source_output_info_cb (pa_context *context, g_object_notify (G_OBJECT (self), "microphone"); } +static void +empathy_audio_src_source_info_cb (pa_context *context, + const pa_source_info *info, + int eol, + void *userdata) +{ + EmpathyGstAudioSrc *self = userdata; + + if (eol) + return; + + g_signal_emit (self, signals[MICROPHONE_ADDED], 0, + info->index, info->name, info->description); +} + +static void +empathy_audio_src_pa_event_cb (pa_context *context, + pa_subscription_event_type_t type, + uint32_t idx, + void *userdata) +{ + EmpathyGstAudioSrc *self = userdata; + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT + && (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE + && idx == priv->source_output_idx) + { + /* Microphone in the source output has changed */ + pa_context_get_source_output_info (context, idx, + empathy_audio_src_source_output_info_cb, self); + } + else if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE + && (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) + { + /* A mic has been removed */ + g_signal_emit (self, signals[MICROPHONE_REMOVED], 0, idx); + } + else if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE + && (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) + { + /* A mic has been plugged in */ + pa_context_get_source_info_by_index (context, idx, + empathy_audio_src_source_info_cb, self); + } +} + +static void +empathy_audio_src_pa_subscribe_cb (pa_context *context, + int success, + void *userdata) +{ + if (!success) + g_debug ("Failed to subscribe to PulseAudio events"); +} + +static void +empathy_audio_src_pa_state_change_cb (pa_context *context, + void *userdata) +{ + EmpathyGstAudioSrc *self = userdata; + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + pa_context_state_t state = pa_context_get_state (priv->context); + + if (state == PA_CONTEXT_READY) + { + /* Listen to pulseaudio events so we know when sources are + * added and when the microphone is changed. */ + pa_context_set_subscribe_callback (priv->context, + empathy_audio_src_pa_event_cb, self); + pa_context_subscribe (priv->context, + PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, + empathy_audio_src_pa_subscribe_cb, NULL); + } + + operations_run (self); +} + static void empathy_audio_src_stream_index_notify (GObject *object, GParamSpec *pspec, @@ -327,11 +400,6 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) priv->context = pa_context_new (pa_glib_mainloop_get_api (priv->loop), "EmpathyAudioSrc"); - /* Now listen for state changes so we know when we've connected. */ - pa_context_set_state_callback (priv->context, - empathy_audio_src_pa_state_change_cb, obj); - pa_context_connect (priv->context, NULL, 0, NULL); - /* Listen to changes to GstPulseSrc:stream-index so we know when * it's no longer G_MAXUINT (starting for the first time) or if it * changes (READY->NULL->READY...) */ @@ -339,6 +407,12 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) G_CALLBACK (empathy_audio_src_stream_index_notify), obj); + /* Finally listen for state changes so we know when we've + * connected. */ + pa_context_set_state_callback (priv->context, + empathy_audio_src_pa_state_change_cb, obj); + pa_context_connect (priv->context, NULL, 0, NULL); + priv->operations = g_queue_new (); } @@ -451,6 +525,22 @@ empathy_audio_src_class_init (EmpathyGstAudioSrcClass NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE); + + signals[MICROPHONE_ADDED] = g_signal_new ("microphone-added", + G_TYPE_FROM_CLASS (empathy_audio_src_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _src_marshal_VOID__UINT_STRING_STRING, + G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); + + signals[MICROPHONE_REMOVED] = g_signal_new ("microphone-removed", + G_TYPE_FROM_CLASS (empathy_audio_src_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); } void -- cgit v1.2.3 From dbddd441789b9a5ed3ebde3f870b9337d0c82a47 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 17:49:41 +0100 Subject: audio-src: set property IDs properly Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index d44298fd8..7403d9cf4 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -497,7 +497,7 @@ empathy_audio_src_class_init (EmpathyGstAudioSrcClass param_spec = g_param_spec_double ("peak-level", "peak level", "peak level", -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VOLUME, param_spec); + g_object_class_install_property (object_class, PROP_PEAK_LEVEL, param_spec); param_spec = g_param_spec_uint ("microphone", "microphone", "microphone", 0, G_MAXUINT, G_MAXUINT, @@ -515,7 +515,7 @@ empathy_audio_src_class_init (EmpathyGstAudioSrcClass param_spec = g_param_spec_double ("rms-level", "RMS level", "RMS level", -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VOLUME, param_spec); + g_object_class_install_property (object_class, PROP_RMS_LEVEL, param_spec); signals[RMS_LEVEL_CHANGED] = g_signal_new ("rms-level-changed", -- cgit v1.2.3 From 7a58752393cb6ca9f55c2824ebab0c7a71311ff8 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Wed, 27 Jul 2011 17:50:15 +0100 Subject: audio-src: add comment about values for unknown values Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 7403d9cf4..3fa614f5f 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -66,7 +66,9 @@ struct _EmpathyGstAudioSrcPrivate pa_context *context; GQueue *operations; + /* 0 if not known yet */ guint source_output_idx; + /* G_MAXUINT if not known yet */ guint source_idx; gdouble peak_level; -- cgit v1.2.3 From 0bc0f8fca1696826af50b21c7339164c61d55764 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Thu, 28 Jul 2011 09:45:11 +0100 Subject: audio-src: don't ignore monitors pavucontrol doesn't... Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 3fa614f5f..9f6b9c86c 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -153,10 +153,6 @@ operation_get_microphones_cb (pa_context *context, return; } - /* ignore monitors */ - if (info->monitor_of_sink != PA_INVALID_INDEX) - return; - mic = g_slice_new0 (EmpathyAudioSrcMicrophone); mic->index = info->index; mic->name = g_strdup (info->name); -- cgit v1.2.3 From 58df02da291709b265717d8bf2d196e4345ea2ba Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Thu, 28 Jul 2011 12:38:26 +0100 Subject: call-window: add getters for the UI manager and audio src Signed-off-by: Jonny Lamb --- src/empathy-call-window.c | 16 ++++++++++++++++ src/empathy-call-window.h | 5 +++++ 2 files changed, 21 insertions(+) (limited to 'src') diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c index 3bd6d746d..8407dc852 100644 --- a/src/empathy-call-window.c +++ b/src/empathy-call-window.c @@ -3257,3 +3257,19 @@ empathy_call_window_volume_changed_cb (GtkScaleButton *button, empathy_audio_sink_set_volume (EMPATHY_GST_AUDIO_SINK (priv->audio_output), value); } + +GtkUIManager * +empathy_call_window_get_ui_manager (EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + return priv->ui_manager; +} + +EmpathyGstAudioSrc * +empathy_call_window_get_audio_src (EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + return (EmpathyGstAudioSrc *) priv->audio_input; +} diff --git a/src/empathy-call-window.h b/src/empathy-call-window.h index 11237fff6..357d6f160 100644 --- a/src/empathy-call-window.h +++ b/src/empathy-call-window.h @@ -25,6 +25,7 @@ #include #include "empathy-call-handler.h" +#include "empathy-audio-src.h" G_BEGIN_DECLS @@ -62,6 +63,10 @@ GType empathy_call_window_get_type (void); EmpathyCallWindow *empathy_call_window_new (EmpathyCallHandler *handler); +GtkUIManager *empathy_call_window_get_ui_manager (EmpathyCallWindow *window); + +EmpathyGstAudioSrc *empathy_call_window_get_audio_src (EmpathyCallWindow *window); + G_END_DECLS #endif /* #ifndef __EMPATHY_CALL_WINDOW_H__*/ -- cgit v1.2.3 From a36214f589404b37c6125b0a3faa756f9e001cd6 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Thu, 28 Jul 2011 12:45:21 +0100 Subject: call-window: add a Microphone menu to change mic on the fly Yay! Sorry this commit is kind of big with the addition of mic-menu, perhaps I should have added it in pieces. Signed-off-by: Jonny Lamb --- src/Makefile.am | 4 +- src/empathy-call-window.c | 6 + src/empathy-call-window.ui | 16 ++ src/empathy-mic-menu.c | 392 +++++++++++++++++++++++++++++++++++++++++++++ src/empathy-mic-menu.h | 56 +++++++ 5 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 src/empathy-mic-menu.c create mode 100644 src/empathy-mic-menu.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index e6574077d..c232652c1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -168,7 +168,9 @@ empathy_call_SOURCES = \ empathy-video-widget.c \ empathy-video-widget.h \ ev-sidebar.c \ - ev-sidebar.h + ev-sidebar.h \ + empathy-mic-menu.c \ + empathy-mic-menu.h nodist_empathy_call_SOURCES = $(BUILT_SOURCES) diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c index 8407dc852..afd02522b 100644 --- a/src/empathy-call-window.c +++ b/src/empathy-call-window.c @@ -60,6 +60,7 @@ #include "empathy-audio-sink.h" #include "empathy-video-src.h" #include "ev-sidebar.h" +#include "empathy-mic-menu.h" #define CONTENT_HBOX_BORDER_WIDTH 6 #define CONTENT_HBOX_SPACING 3 @@ -218,6 +219,8 @@ struct _EmpathyCallWindowPriv gboolean pipeline_playing; EmpathySoundManager *sound_mgr; + + EmpathyMicMenu *mic_menu; }; #define GET_PRIV(o) (EMPATHY_CALL_WINDOW (o)->priv) @@ -1154,6 +1157,7 @@ empathy_call_window_init (EmpathyCallWindow *self) g_object_unref (gui); priv->sound_mgr = empathy_sound_manager_dup_singleton (); + priv->mic_menu = empathy_mic_menu_new (self); empathy_call_window_show_hangup_button (self, TRUE); @@ -1684,6 +1688,8 @@ empathy_call_window_dispose (GObject *object) tp_clear_object (&priv->sound_mgr); + tp_clear_object (&priv->mic_menu); + G_OBJECT_CLASS (empathy_call_window_parent_class)->dispose (object); } diff --git a/src/empathy-call-window.ui b/src/empathy-call-window.ui index bbcd97226..8c0d5777e 100644 --- a/src/empathy-call-window.ui +++ b/src/empathy-call-window.ui @@ -23,6 +23,19 @@ _Sidebar + + + edit + _Edit + + + + + _Microphone + menumicrophone + gnome-stock-mic + + view @@ -61,6 +74,9 @@ + + + diff --git a/src/empathy-mic-menu.c b/src/empathy-mic-menu.c new file mode 100644 index 000000000..a2cc34ccf --- /dev/null +++ b/src/empathy-mic-menu.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2011 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * GtkAction code based on gnome-terminal's TerminalTabsMenu object. + * Thanks guys! + */ + +#include + +#include + +#include "empathy-mic-menu.h" + +struct _EmpathyMicMenuPrivate +{ + /* Borrowed ref; the call window actually owns us. */ + EmpathyCallWindow *window; + + /* Given away ref; the call window's UI manager now owns this. */ + GtkActionGroup *action_group; + + /* An invisible radio action so new microphones are always in the + * same radio group. */ + GtkAction *anchor_action; + + /* The merge ID used with the UI manager. We need to keep this + * around so in _clean we can remove all the items we've added + * before and start again. */ + guint ui_id; + + /* TRUE if we're in _update and so calling _set_active. */ + gboolean in_update; + + /* Queue of GtkRadioActions. */ + GQueue *microphones; +}; + +G_DEFINE_TYPE (EmpathyMicMenu, empathy_mic_menu, G_TYPE_OBJECT); + +enum +{ + PROP_WINDOW = 1, +}; + +static void empathy_mic_menu_update (EmpathyMicMenu *self); + +static void +empathy_mic_menu_init (EmpathyMicMenu *self) +{ + EmpathyMicMenuPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + EMPATHY_TYPE_MIC_MENU, EmpathyMicMenuPrivate); + + self->priv = priv; +} + +static void +empathy_mic_menu_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyMicMenu *self = EMPATHY_MIC_MENU (object); + EmpathyMicMenuPrivate *priv = self->priv; + + switch (property_id) + { + case PROP_WINDOW: + priv->window = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_mic_menu_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyMicMenu *self = EMPATHY_MIC_MENU (object); + EmpathyMicMenuPrivate *priv = self->priv; + + switch (property_id) + { + case PROP_WINDOW: + g_value_set_object (value, priv->window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_mic_menu_clean (EmpathyMicMenu *self) +{ + EmpathyMicMenuPrivate *priv = self->priv; + GtkUIManager *ui_manager; + + if (priv->ui_id == 0) + return; + + ui_manager = empathy_call_window_get_ui_manager (priv->window); + + gtk_ui_manager_remove_ui (ui_manager, priv->ui_id); + gtk_ui_manager_ensure_update (ui_manager); + priv->ui_id = 0; +} + +static void +empathy_mic_menu_change_mic_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyGstAudioSrc *audio = EMPATHY_GST_AUDIO_SRC (source_object); + EmpathyMicMenu *self = user_data; + GError *error = NULL; + + if (!empathy_audio_src_change_microphone_finish (audio, result, &error)) + { + g_debug ("Failed to change microphone: %s", error->message); + g_clear_error (&error); + + /* We call update here because if this change operation failed + * and we don't update the menu items, it'll point to the wrong + * device. We don't want to call it if the change was successful + * because we'll get the notify::microphone signal fired in a + * bit and the current value hasn't changed so it'd keep jumping + * between these values like there's no tomorrow, etc. */ + empathy_mic_menu_update (self); + } +} + +static void +empathy_mic_menu_activate_cb (GtkToggleAction *action, + EmpathyMicMenu *self) +{ + EmpathyMicMenuPrivate *priv = self->priv; + EmpathyGstAudioSrc *audio; + gint value; + + if (priv->in_update) + return; + + audio = empathy_call_window_get_audio_src (priv->window); + + g_object_get (action, "value", &value, NULL); + + empathy_audio_src_change_microphone_async (audio, value, + empathy_mic_menu_change_mic_cb, self); +} + +static void +empathy_mic_menu_update (EmpathyMicMenu *self) +{ + EmpathyMicMenuPrivate *priv = self->priv; + GList *l; + GtkUIManager *ui_manager; + EmpathyGstAudioSrc *audio; + guint current_mic; + + ui_manager = empathy_call_window_get_ui_manager (priv->window); + + audio = empathy_call_window_get_audio_src (priv->window); + current_mic = empathy_audio_src_get_microphone (audio); + + empathy_mic_menu_clean (self); + priv->ui_id = gtk_ui_manager_new_merge_id (ui_manager); + + for (l = priv->microphones->head; l != NULL; l = l->next) + { + GtkRadioAction *action = l->data; + const gchar *name = gtk_action_get_name (GTK_ACTION (action)); + gint value; + + g_object_get (action, "value", &value, NULL); + + if (value == (gint) current_mic) + { + priv->in_update = TRUE; + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + priv->in_update = FALSE; + } + + gtk_ui_manager_add_ui (ui_manager, priv->ui_id, + /* TODO: this should probably be passed from the call + * window, seeing that it's a reference to + * empathy-call-window.ui. */ + "/menubar1/edit/menumicrophone", + name, name, GTK_UI_MANAGER_MENUITEM, FALSE); + } +} + +static void +empathy_mic_menu_add_microphone (EmpathyMicMenu *self, + const gchar *name, + const gchar *description, + guint source_idx) +{ + EmpathyMicMenuPrivate *priv = self->priv; + GtkRadioAction *action; + GSList *group; + + action = gtk_radio_action_new (name, description, NULL, NULL, source_idx); + gtk_action_group_add_action_with_accel (priv->action_group, + GTK_ACTION (action), NULL); + + group = gtk_radio_action_get_group (GTK_RADIO_ACTION (priv->anchor_action)); + gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group); + + g_queue_push_tail (priv->microphones, action); + + g_signal_connect (action, "activate", + G_CALLBACK (empathy_mic_menu_activate_cb), self); +} + +static void +empathy_mic_menu_notify_microphone_cb (EmpathyGstAudioSrc *audio, + GParamSpec *pspec, + EmpathyMicMenu *self) +{ + empathy_mic_menu_update (self); +} + +static void +empathy_mic_menu_microphone_added_cb (EmpathyGstAudioSrc *audio, + guint source_idx, + const gchar *name, + const gchar *description, + EmpathyMicMenu *self) +{ + empathy_mic_menu_add_microphone (self, name, description, source_idx); + + empathy_mic_menu_update (self); +} + +static void +empathy_mic_menu_microphone_removed_cb (EmpathyGstAudioSrc *audio, + guint source_idx, + EmpathyMicMenu *self) +{ + EmpathyMicMenuPrivate *priv = self->priv; + GList *l; + + for (l = priv->microphones->head; l != NULL; l = l->next) + { + GtkRadioAction *action = l->data; + gint value; + + g_object_get (action, "value", &value, NULL); + + if (value != (gint) source_idx) + { + action = NULL; + continue; + } + + g_signal_handlers_disconnect_by_func (action, + G_CALLBACK (empathy_mic_menu_activate_cb), self); + + gtk_action_group_remove_action (priv->action_group, GTK_ACTION (action)); + g_queue_remove (priv->microphones, action); + break; + } + + empathy_mic_menu_update (self); +} + +static void +empathy_mic_menu_get_microphones_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyGstAudioSrc *audio = EMPATHY_GST_AUDIO_SRC (source_object); + EmpathyMicMenu *self = user_data; + GError *error = NULL; + const GList *mics = NULL; + + mics = empathy_audio_src_get_microphones_finish (audio, result, &error); + + if (error != NULL) + { + g_debug ("Failed to get microphone list: %s", error->message); + g_clear_error (&error); + return; + } + + for (; mics != NULL; mics = mics->next) + { + EmpathyAudioSrcMicrophone *mic = mics->data; + + empathy_mic_menu_add_microphone (self, mic->name, + mic->description, mic->index); + } + + empathy_mic_menu_update (self); +} + +static void +empathy_mic_menu_constructed (GObject *obj) +{ + EmpathyMicMenu *self = EMPATHY_MIC_MENU (obj); + EmpathyMicMenuPrivate *priv = self->priv; + GtkUIManager *ui_manager; + EmpathyGstAudioSrc *audio; + + g_assert (EMPATHY_IS_CALL_WINDOW (priv->window)); + + ui_manager = empathy_call_window_get_ui_manager (priv->window); + audio = empathy_call_window_get_audio_src (priv->window); + + g_assert (GTK_IS_UI_MANAGER (ui_manager)); + g_assert (EMPATHY_IS_GST_AUDIO_SRC (audio)); + + /* Okay let's go go go. */ + + priv->action_group = gtk_action_group_new ("EmpathyMicMenu"); + gtk_ui_manager_insert_action_group (ui_manager, priv->action_group, -1); + /* the UI manager now owns this */ + g_object_unref (priv->action_group); + + priv->anchor_action = g_object_new (GTK_TYPE_RADIO_ACTION, + "name", "EmpathyMicMenuAnchorAction", + NULL); + gtk_action_group_add_action (priv->action_group, priv->anchor_action); + g_object_unref (priv->anchor_action); + + tp_g_signal_connect_object (audio, "notify::microphone", + G_CALLBACK (empathy_mic_menu_notify_microphone_cb), self, 0); + tp_g_signal_connect_object (audio, "microphone-added", + G_CALLBACK (empathy_mic_menu_microphone_added_cb), self, 0); + tp_g_signal_connect_object (audio, "microphone-removed", + G_CALLBACK (empathy_mic_menu_microphone_removed_cb), self, 0); + + priv->microphones = g_queue_new (); + + empathy_audio_src_get_microphones_async (audio, + empathy_mic_menu_get_microphones_cb, self); +} + +static void +empathy_mic_menu_dispose (GObject *obj) +{ + EmpathyMicMenu *self = EMPATHY_MIC_MENU (obj); + EmpathyMicMenuPrivate *priv = self->priv; + + if (priv->microphones != NULL) + g_queue_free (priv->microphones); + priv->microphones = NULL; + + G_OBJECT_CLASS (empathy_mic_menu_parent_class)->dispose (obj); +} + +static void +empathy_mic_menu_class_init (EmpathyMicMenuClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = empathy_mic_menu_set_property; + object_class->get_property = empathy_mic_menu_get_property; + object_class->constructed = empathy_mic_menu_constructed; + object_class->dispose = empathy_mic_menu_dispose; + + g_object_class_install_property (object_class, PROP_WINDOW, + g_param_spec_object ("window", "window", "window", + EMPATHY_TYPE_CALL_WINDOW, + G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof (EmpathyMicMenuPrivate)); +} + +EmpathyMicMenu * +empathy_mic_menu_new (EmpathyCallWindow *window) +{ + return g_object_new (EMPATHY_TYPE_MIC_MENU, + "window", window, + NULL); +} diff --git a/src/empathy-mic-menu.h b/src/empathy-mic-menu.h new file mode 100644 index 000000000..87691ae6d --- /dev/null +++ b/src/empathy-mic-menu.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EMPATHY_MIC_MENU_H__ +#define __EMPATHY_MIC_MENU_H__ + +#include + +#include "empathy-call-window.h" + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_MIC_MENU (empathy_mic_menu_get_type ()) +#define EMPATHY_MIC_MENU(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_MIC_MENU, EmpathyMicMenu)) +#define EMPATHY_MIC_MENU_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_MIC_MENU, EmpathyMicMenuClass)) +#define EMPATHY_IS_MIC_MENU(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_MIC_MENU)) +#define EMPATHY_IS_MIC_MENU_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_MIC_MENU)) +#define EMPATHY_MIC_MENU_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_MIC_MENU, EmpathyMicMenuClass)) + +typedef struct _EmpathyMicMenu EmpathyMicMenu; +typedef struct _EmpathyMicMenuPrivate EmpathyMicMenuPrivate; +typedef struct _EmpathyMicMenuClass EmpathyMicMenuClass; + +struct _EmpathyMicMenu +{ + GObject parent; + EmpathyMicMenuPrivate *priv; +}; + +struct _EmpathyMicMenuClass +{ + GObjectClass parent_class; +}; + +GType empathy_mic_menu_get_type (void) G_GNUC_CONST; + +EmpathyMicMenu * empathy_mic_menu_new (EmpathyCallWindow *window); + +G_END_DECLS + +#endif /* __EMPATHY_MIC_MENU_H__ */ -- cgit v1.2.3 From 90eaac49d3f279ae20fa061adbe8ba9ac8aaf023 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Thu, 28 Jul 2011 15:24:19 +0100 Subject: audio-src: add is_monitor boolean to mic struct Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 10 +++++++--- src/empathy-audio-src.h | 1 + src/empathy-mic-menu.c | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 9f6b9c86c..3be96a996 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -157,6 +157,7 @@ operation_get_microphones_cb (pa_context *context, mic->index = info->index; mic->name = g_strdup (info->name); mic->description = g_strdup (info->description); + mic->is_monitor = (info->monitor_of_sink != PA_INVALID_INDEX); /* add it to the queue */ queue = g_simple_async_result_get_op_res_gpointer (result); @@ -264,12 +265,15 @@ empathy_audio_src_source_info_cb (pa_context *context, void *userdata) { EmpathyGstAudioSrc *self = userdata; + gboolean is_monitor; if (eol) return; + is_monitor = (info->monitor_of_sink != PA_INVALID_INDEX); + g_signal_emit (self, signals[MICROPHONE_ADDED], 0, - info->index, info->name, info->description); + info->index, info->name, info->description, is_monitor); } static void @@ -529,8 +533,8 @@ empathy_audio_src_class_init (EmpathyGstAudioSrcClass G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _src_marshal_VOID__UINT_STRING_STRING, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); + _src_marshal_VOID__UINT_STRING_STRING_BOOLEAN, + G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); signals[MICROPHONE_REMOVED] = g_signal_new ("microphone-removed", G_TYPE_FROM_CLASS (empathy_audio_src_class), diff --git a/src/empathy-audio-src.h b/src/empathy-audio-src.h index 286a34f9a..05e3c46cc 100644 --- a/src/empathy-audio-src.h +++ b/src/empathy-audio-src.h @@ -67,6 +67,7 @@ typedef struct guint index; gchar *name; gchar *description; + gboolean is_monitor; } EmpathyAudioSrcMicrophone; void empathy_audio_src_get_microphones_async (EmpathyGstAudioSrc *src, diff --git a/src/empathy-mic-menu.c b/src/empathy-mic-menu.c index a2cc34ccf..1053b7129 100644 --- a/src/empathy-mic-menu.c +++ b/src/empathy-mic-menu.c @@ -241,6 +241,7 @@ empathy_mic_menu_microphone_added_cb (EmpathyGstAudioSrc *audio, guint source_idx, const gchar *name, const gchar *description, + gboolean is_monitor, EmpathyMicMenu *self) { empathy_mic_menu_add_microphone (self, name, description, source_idx); -- cgit v1.2.3 From 302af77150e52cb625bc3e164808bd812979cc32 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Thu, 28 Jul 2011 15:29:44 +0100 Subject: mic-menu: display monitors when they're the current mic ...but otherwise hide them. Signed-off-by: Jonny Lamb --- src/empathy-mic-menu.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/empathy-mic-menu.c b/src/empathy-mic-menu.c index 1053b7129..3ebd31c27 100644 --- a/src/empathy-mic-menu.c +++ b/src/empathy-mic-menu.c @@ -51,6 +51,8 @@ struct _EmpathyMicMenuPrivate G_DEFINE_TYPE (EmpathyMicMenu, empathy_mic_menu, G_TYPE_OBJECT); +#define MONITOR_KEY "empathy-mic-menu-is-monitor" + enum { PROP_WINDOW = 1, @@ -186,16 +188,28 @@ empathy_mic_menu_update (EmpathyMicMenu *self) GtkRadioAction *action = l->data; const gchar *name = gtk_action_get_name (GTK_ACTION (action)); gint value; + gboolean active; g_object_get (action, "value", &value, NULL); - if (value == (gint) current_mic) + active = (value == (gint) current_mic); + + if (active) { priv->in_update = TRUE; gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); priv->in_update = FALSE; } + /* If action is a monitor then don't show it in the UI, BUT do + * display it regardless if it is the current device. This is so + * we don't have a rubbish UI by showing monitor devices in + * Empathy, but still show the correct device when someone plays + * with pavucontrol. */ + if (g_object_get_data (G_OBJECT (action), MONITOR_KEY) != NULL + && !active) + continue; + gtk_ui_manager_add_ui (ui_manager, priv->ui_id, /* TODO: this should probably be passed from the call * window, seeing that it's a reference to @@ -209,7 +223,8 @@ static void empathy_mic_menu_add_microphone (EmpathyMicMenu *self, const gchar *name, const gchar *description, - guint source_idx) + guint source_idx, + gboolean is_monitor) { EmpathyMicMenuPrivate *priv = self->priv; GtkRadioAction *action; @@ -219,6 +234,14 @@ empathy_mic_menu_add_microphone (EmpathyMicMenu *self, gtk_action_group_add_action_with_accel (priv->action_group, GTK_ACTION (action), NULL); + /* Set MONITOR_KEY on the action to non-NULL if it's a monitor + * because we don't want to show monitors if we can help it. */ + if (is_monitor) + { + g_object_set_data (G_OBJECT (action), MONITOR_KEY, + GUINT_TO_POINTER (TRUE)); + } + group = gtk_radio_action_get_group (GTK_RADIO_ACTION (priv->anchor_action)); gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group); @@ -244,7 +267,8 @@ empathy_mic_menu_microphone_added_cb (EmpathyGstAudioSrc *audio, gboolean is_monitor, EmpathyMicMenu *self) { - empathy_mic_menu_add_microphone (self, name, description, source_idx); + empathy_mic_menu_add_microphone (self, name, description, + source_idx, is_monitor); empathy_mic_menu_update (self); } @@ -305,7 +329,7 @@ empathy_mic_menu_get_microphones_cb (GObject *source_object, EmpathyAudioSrcMicrophone *mic = mics->data; empathy_mic_menu_add_microphone (self, mic->name, - mic->description, mic->index); + mic->description, mic->index, mic->is_monitor); } empathy_mic_menu_update (self); -- cgit v1.2.3 From a19f10561bf7ad86ff9f688f78df6a9df7a13899 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Fri, 29 Jul 2011 11:06:25 +0100 Subject: audio-src: only call operations_run when PA is ready Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 3be96a996..5487fead3 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -334,9 +334,9 @@ empathy_audio_src_pa_state_change_cb (pa_context *context, pa_context_subscribe (priv->context, PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, empathy_audio_src_pa_subscribe_cb, NULL); - } - operations_run (self); + operations_run (self); + } } static void -- cgit v1.2.3 From 89afdf6b8941ac525104cfb54f10174d6cb7dbcf Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Fri, 29 Jul 2011 11:09:15 +0100 Subject: audio-src,mic-menu: use DEBUG macros Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 5 ++++- src/empathy-mic-menu.c | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 5487fead3..4c1072c44 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -31,6 +31,9 @@ #include "src-marshal.h" +#define DEBUG_FLAG EMPATHY_DEBUG_VOIP +#include + G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN) /* signal enum */ @@ -314,7 +317,7 @@ empathy_audio_src_pa_subscribe_cb (pa_context *context, void *userdata) { if (!success) - g_debug ("Failed to subscribe to PulseAudio events"); + DEBUG ("Failed to subscribe to PulseAudio events"); } static void diff --git a/src/empathy-mic-menu.c b/src/empathy-mic-menu.c index 3ebd31c27..dc3d0f006 100644 --- a/src/empathy-mic-menu.c +++ b/src/empathy-mic-menu.c @@ -25,6 +25,9 @@ #include "empathy-mic-menu.h" +#define DEBUG_FLAG EMPATHY_DEBUG_VOIP +#include + struct _EmpathyMicMenuPrivate { /* Borrowed ref; the call window actually owns us. */ @@ -134,7 +137,7 @@ empathy_mic_menu_change_mic_cb (GObject *source_object, if (!empathy_audio_src_change_microphone_finish (audio, result, &error)) { - g_debug ("Failed to change microphone: %s", error->message); + DEBUG ("Failed to change microphone: %s", error->message); g_clear_error (&error); /* We call update here because if this change operation failed @@ -319,7 +322,7 @@ empathy_mic_menu_get_microphones_cb (GObject *source_object, if (error != NULL) { - g_debug ("Failed to get microphone list: %s", error->message); + DEBUG ("Failed to get microphone list: %s", error->message); g_clear_error (&error); return; } -- cgit v1.2.3 From cf7f9a1da8e7a830a0f0676accc0afa444ae8748 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Fri, 29 Jul 2011 11:43:44 +0100 Subject: audio-src: update to newer GstPulseSrc API This time it's actually merged to master. Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 4c1072c44..129e75319 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -204,17 +204,17 @@ operation_change_microphone (EmpathyGstAudioSrc *self, GSimpleAsyncResult *result) { EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - guint stream_idx, microphone; + guint source_output_idx, microphone; - g_object_get (priv->src, "stream-index", &stream_idx, NULL); + g_object_get (priv->src, "source-output-index", &source_output_idx, NULL); g_assert_cmpuint (pa_context_get_state (priv->context), ==, PA_CONTEXT_READY); - g_assert_cmpuint (stream_idx, !=, G_MAXUINT); + g_assert_cmpuint (source_output_idx, !=, PA_INVALID_INDEX); microphone = GPOINTER_TO_UINT ( g_simple_async_result_get_op_res_gpointer (result)); - pa_context_move_source_output_by_index (priv->context, stream_idx, microphone, + pa_context_move_source_output_by_index (priv->context, source_output_idx, microphone, operation_change_microphone_cb, result); } @@ -343,25 +343,25 @@ empathy_audio_src_pa_state_change_cb (pa_context *context, } static void -empathy_audio_src_stream_index_notify (GObject *object, +empathy_audio_src_source_output_index_notify (GObject *object, GParamSpec *pspec, EmpathyGstAudioSrc *self) { EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - guint stream_idx = G_MAXUINT; + guint source_output_idx = PA_INVALID_INDEX; - g_object_get (priv->src, "stream-index", &stream_idx, NULL); + g_object_get (priv->src, "source-output-index", &source_output_idx, NULL); - if (stream_idx == G_MAXUINT) + if (source_output_idx == PA_INVALID_INDEX) return; - if (priv->source_output_idx == stream_idx) + if (priv->source_output_idx == source_output_idx) return; /* It's actually changed. */ - priv->source_output_idx = stream_idx; + priv->source_output_idx = source_output_idx; - pa_context_get_source_output_info (priv->context, stream_idx, + pa_context_get_source_output_info (priv->context, source_output_idx, empathy_audio_src_source_output_info_cb, self); } @@ -405,11 +405,11 @@ empathy_audio_src_init (EmpathyGstAudioSrc *obj) priv->context = pa_context_new (pa_glib_mainloop_get_api (priv->loop), "EmpathyAudioSrc"); - /* Listen to changes to GstPulseSrc:stream-index so we know when - * it's no longer G_MAXUINT (starting for the first time) or if it + /* Listen to changes to GstPulseSrc:source-output-index so we know when + * it's no longer PA_INVALID_INDEX (starting for the first time) or if it * changes (READY->NULL->READY...) */ - g_signal_connect (priv->src, "notify::stream-index", - G_CALLBACK (empathy_audio_src_stream_index_notify), + g_signal_connect (priv->src, "notify::source-output-index", + G_CALLBACK (empathy_audio_src_source_output_index_notify), obj); /* Finally listen for state changes so we know when we've @@ -771,16 +771,16 @@ empathy_audio_src_change_microphone_async (EmpathyGstAudioSrc *src, gpointer user_data) { EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); - guint stream_idx; + guint source_output_idx; GSimpleAsyncResult *simple; Operation *operation; simple = g_simple_async_result_new (G_OBJECT (src), callback, user_data, empathy_audio_src_change_microphone_async); - g_object_get (priv->src, "stream-index", &stream_idx, NULL); + g_object_get (priv->src, "source-output-index", &source_output_idx, NULL); - if (stream_idx == G_MAXUINT) + if (source_output_idx == PA_INVALID_INDEX) { g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, "pulsesrc is not yet PLAYING"); -- cgit v1.2.3 From e17e6184ca30b2164e7b30d1a35f504b87973400 Mon Sep 17 00:00:00 2001 From: Jonny Lamb Date: Fri, 29 Jul 2011 18:54:40 +0100 Subject: audio-src: check for new enough pulsesrc before trying to change mics This means this feature will automatically start working when a new enough pulsesrc is used. Making _get_microphones() fail has a nice side-effect that the Edit menu item doesn't appear at all. Neat. Signed-off-by: Jonny Lamb --- src/empathy-audio-src.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src') diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c index 129e75319..642628d7b 100644 --- a/src/empathy-audio-src.c +++ b/src/empathy-audio-src.c @@ -85,6 +85,18 @@ struct _EmpathyGstAudioSrcPrivate (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \ EmpathyGstAudioSrcPrivate)) +static gboolean +empathy_audio_src_supports_changing_mic (EmpathyGstAudioSrc *self) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + GObjectClass *object_class; + + object_class = G_OBJECT_GET_CLASS (priv->src); + + return (g_object_class_find_property (object_class, + "source-output-index") != NULL); +} + typedef void (*OperationFunc) (EmpathyGstAudioSrc *, GSimpleAsyncResult *); typedef struct @@ -730,6 +742,17 @@ empathy_audio_src_get_microphones_async (EmpathyGstAudioSrc *src, simple = g_simple_async_result_new (G_OBJECT (src), callback, user_data, empathy_audio_src_get_microphones_async); + /* If we can't change mic let's not pretend we can by returning the + * list of available mics. */ + if (!empathy_audio_src_supports_changing_mic (src)) + { + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + "pulsesrc is not new enough to support changing microphone"); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + operation = operation_new (operation_get_microphones, simple); g_queue_push_tail (priv->operations, operation); @@ -778,6 +801,15 @@ empathy_audio_src_change_microphone_async (EmpathyGstAudioSrc *src, simple = g_simple_async_result_new (G_OBJECT (src), callback, user_data, empathy_audio_src_change_microphone_async); + if (!empathy_audio_src_supports_changing_mic (src)) + { + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + "pulsesrc is not new enough to support changing microphone"); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + g_object_get (priv->src, "source-output-index", &source_output_idx, NULL); if (source_output_idx == PA_INVALID_INDEX) -- cgit v1.2.3