diff options
author | Mike Ruprecht <mike.ruprecht@collabora.co.uk> | 2011-07-21 23:05:29 -0500 |
---|---|---|
committer | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2011-11-14 11:40:24 +0100 |
commit | 017e178f7aca7ee8ec346a6c7574b34eb3ab66f6 (patch) | |
tree | 7320575e8fbbbc0b31b79d421e7ce5e753e3f230 | |
parent | 3426e3c0f34df7d94d27bad95d6683d2ad6de375 (diff) |
Add bindings for the CallContent's AudioControl interface
-rw-r--r-- | telepathy-farstream/call-content.c | 220 |
1 files changed, 219 insertions, 1 deletions
diff --git a/telepathy-farstream/call-content.c b/telepathy-farstream/call-content.c index a6fc408..e4e9304 100644 --- a/telepathy-farstream/call-content.c +++ b/telepathy-farstream/call-content.c @@ -75,6 +75,10 @@ struct _TfCallContent { gboolean got_codec_offer_property; + /* AudioControl API */ + guint input_volume; + guint output_volume; + /* VideoControl API */ FsElementAddedNotifier *notifier; @@ -110,6 +114,8 @@ enum PROP_SINK_PAD, PROP_MEDIA_TYPE, PROP_OBJECT_PATH, + PROP_INPUT_VOLUME, + PROP_OUTPUT_VOLUME, PROP_FRAMERATE, PROP_WIDTH, PROP_HEIGHT @@ -137,6 +143,11 @@ tf_call_content_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); +static void +tf_call_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); static void tf_call_content_dispose (GObject *object); static void tf_call_content_finalize (GObject *object); @@ -178,6 +189,7 @@ tf_call_content_class_init (TfCallContentClass *klass) object_class->dispose = tf_call_content_dispose; object_class->finalize = tf_call_content_finalize; object_class->get_property = tf_call_content_get_property; + object_class->set_property = tf_call_content_set_property; g_object_class_override_property (object_class, PROP_TF_CHANNEL, "tf-channel"); @@ -200,6 +212,22 @@ tf_call_content_class_init (TfCallContentClass *klass) 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_INPUT_VOLUME, + g_param_spec_uint ("input-volume", + "Input volume", + "The input volume indicated by the AudioControl interface" + "or the media layer", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_OUTPUT_VOLUME, + g_param_spec_uint ("output-volume", + "Output volume", + "The output volume indicated by the AudioControl interface" + "or the media layer", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_WIDTH, g_param_spec_uint ("width", "Width", @@ -344,6 +372,12 @@ tf_call_content_get_property (GObject *object, case PROP_OBJECT_PATH: g_object_get_property (G_OBJECT (self->proxy), "object-path", value); break; + case PROP_INPUT_VOLUME: + g_value_set_uint (value, self->input_volume); + break; + case PROP_OUTPUT_VOLUME: + g_value_set_uint (value, self->output_volume); + break; case PROP_FRAMERATE: g_value_set_uint (value, self->framerate); break; @@ -360,6 +394,50 @@ tf_call_content_get_property (GObject *object, } static void +tf_call_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TfCallContent *self = TF_CALL_CONTENT (object); + + switch (property_id) + { + case PROP_INPUT_VOLUME: + if (self->input_volume == g_value_get_uint (value)) + break; + + /* Guard against early disposal */ + if (self->call_channel == NULL) + break; + + self->input_volume = g_value_get_uint (value); + tf_future_cli_call_content_interface_audio_control_call_set_input_volume ( + self->proxy, -1, self->input_volume, NULL, NULL, NULL, NULL); + g_object_notify_by_pspec (object, pspec); + + break; + case PROP_OUTPUT_VOLUME: + if (self->output_volume == g_value_get_uint (value)) + break; + + /* Guard against early disposal */ + if (self->call_channel == NULL) + break; + + self->input_volume = g_value_get_uint (value); + tf_future_cli_call_content_interface_audio_control_call_set_output_volume ( + self->proxy, -1, self->output_volume, NULL, NULL, NULL, NULL); + g_object_notify_by_pspec (object, pspec); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void create_stream (TfCallContent *self, gchar *stream_path) { GError *error = NULL; @@ -806,6 +884,139 @@ setup_content_media_properties (TfCallContent *self, got_content_media_properties, res, NULL, G_OBJECT (self)); } +static void +on_content_input_volume_changed (TfFutureCallContent *proxy, + guint volume, + gpointer user_data, + GObject *weak_object) +{ + TfCallContent *self = TF_CALL_CONTENT (weak_object); + + /* Guard against early disposal */ + if (self->call_channel == NULL) + return; + + if (self->input_volume == volume) + return; + + self->input_volume = volume; + g_object_notify (weak_object, "input-volume"); +} + +static void +on_content_output_volume_changed (TfFutureCallContent *proxy, + guint volume, + gpointer user_data, + GObject *weak_object) +{ + TfCallContent *self = TF_CALL_CONTENT (weak_object); + + /* Guard against early disposal */ + if (self->call_channel == NULL) + return; + + if (self->output_volume == volume) + return; + + self->output_volume = volume; + g_object_notify (weak_object, "output-volume"); +} + +static void +got_content_audio_control_properties (TpProxy *proxy, GHashTable *properties, + const GError *error, gpointer user_data, GObject *weak_object) +{ + TfCallContent *self = TF_CALL_CONTENT (weak_object); + GSimpleAsyncResult *res = user_data; + guint32 input_volume, output_volume; + gboolean valid; + + if (error) + { + tf_content_error (TF_CONTENT (self), + TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "", + "Error getting the Content's AudioControl properties: %s", + error->message); + g_simple_async_result_set_from_error (res, error); + goto error; + } + + /* Guard against early disposal */ + if (self->call_channel == NULL) + { + g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Call content has been disposed of"); + goto error; + } + + if (properties == NULL) + { + tf_content_error_literal (TF_CONTENT (self), + TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "", + "Error getting the Content's AudioControl properties: " + "there are none"); + g_simple_async_result_set_error (res, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Error getting the AudioControl Content's properties: " + "there are none"); + goto error; + } + + + input_volume = tp_asv_get_uint32 (properties, "InputVolume", &valid); + if (valid) + self->input_volume = input_volume; + + output_volume = tp_asv_get_uint32 (properties, "OutputVolume", &valid); + if (valid) + self->output_volume = output_volume; + + setup_content_media_properties (self, proxy, res); + return; + +error: + g_simple_async_result_complete (res); + g_object_unref (res); + return; +} + +static void +setup_content_audio_control (TfCallContent *self, + TpProxy *proxy, + GSimpleAsyncResult *res) +{ + GError *error = NULL; + + tp_proxy_add_interface_by_id (proxy, + TF_FUTURE_IFACE_QUARK_CALL_CONTENT_INTERFACE_AUDIO_CONTROL); + + if (tf_future_cli_call_content_interface_audio_control_connect_to_input_volume_changed ( + TF_FUTURE_CALL_CONTENT (proxy), + on_content_input_volume_changed, + NULL, NULL, G_OBJECT (self), &error) == NULL) + goto connect_failed; + + if (tf_future_cli_call_content_interface_audio_control_connect_to_output_volume_changed ( + TF_FUTURE_CALL_CONTENT (proxy), + on_content_output_volume_changed, + NULL, NULL, G_OBJECT (self), &error) == NULL) + goto connect_failed; + + tp_cli_dbus_properties_call_get_all (proxy, -1, + TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL, + got_content_audio_control_properties, res, NULL, G_OBJECT (self)); + + return; + +connect_failed: + tf_content_error (TF_CONTENT (self), + TF_FUTURE_CONTENT_REMOVAL_REASON_ERROR, "", + "Error getting the Content's AudioControl properties: %s", + error->message); + g_simple_async_result_take_error (res, error); + g_simple_async_result_complete (res); + g_object_unref (res); +} + static gboolean object_has_property (GObject *object, const gchar *property) { @@ -1020,6 +1231,7 @@ got_content_properties (TpProxy *proxy, GHashTable *out_Properties, guint i; const gchar * const *interfaces; gboolean got_media_interface = FALSE; + gboolean got_audio_control_interface = FALSE; gboolean got_video_control_interface = FALSE; if (error) @@ -1078,6 +1290,10 @@ got_content_properties (TpProxy *proxy, GHashTable *out_Properties, got_media_interface = TRUE; if (!strcmp (interfaces[i], + TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_AUDIO_CONTROL)) + got_audio_control_interface = TRUE; + + if (!strcmp (interfaces[i], TF_FUTURE_IFACE_CALL_CONTENT_INTERFACE_VIDEO_CONTROL)) got_video_control_interface = TRUE; } @@ -1133,7 +1349,9 @@ got_content_properties (TpProxy *proxy, GHashTable *out_Properties, return; } - if (got_video_control_interface) + if (got_audio_control_interface) + setup_content_audio_control (self, proxy, res); + else if (got_video_control_interface) setup_content_video_control (self, proxy, res); else setup_content_media_properties (self, proxy, res); |