summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Ruprecht <mike.ruprecht@collabora.co.uk>2011-07-21 23:05:29 -0500
committerSjoerd Simons <sjoerd.simons@collabora.co.uk>2011-11-14 11:40:24 +0100
commit017e178f7aca7ee8ec346a6c7574b34eb3ab66f6 (patch)
tree7320575e8fbbbc0b31b79d421e7ce5e753e3f230
parent3426e3c0f34df7d94d27bad95d6683d2ad6de375 (diff)
Add bindings for the CallContent's AudioControl interface
-rw-r--r--telepathy-farstream/call-content.c220
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);