summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-20 10:34:12 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-30 09:45:32 +0200
commit0f205be359d813369defe3f0d72022657b90fdf1 (patch)
tree376023c90033a50f6f1396df0031361cdb20e9b3
parent088ab9f68b221949c3142612f32b53e4c9870aa2 (diff)
TpTextChannel: add TP_TEXT_CHANNEL_FEATURE_SMS (#37358)
-rw-r--r--docs/reference/telepathy-glib-sections.txt4
-rw-r--r--telepathy-glib/text-channel.c200
-rw-r--r--telepathy-glib/text-channel.h8
-rw-r--r--tests/dbus/text-channel.c88
4 files changed, 299 insertions, 1 deletions
diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index 927e554a..f1ad4dc7 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -5607,6 +5607,9 @@ tp_text_channel_ack_message_finish
tp_text_channel_set_chat_state_async
tp_text_channel_set_chat_state_finish
tp_text_channel_supports_message_type
+TP_TEXT_CHANNEL_FEATURE_SMS
+tp_text_channel_is_sms_channel
+tp_text_channel_get_sms_flash
<SUBSECTION Standard>
TP_IS_TEXT_CHANNEL
TP_IS_TEXT_CHANNEL_CLASS
@@ -5618,4 +5621,5 @@ tp_text_channel_get_type
TpTextChannelPrivate
<SUBSECTION Private>
tp_text_channel_get_feature_quark_incoming_messages
+tp_text_channel_get_feature_quark_sms
</SECTION>
diff --git a/telepathy-glib/text-channel.c b/telepathy-glib/text-channel.c
index 1949746a..db0bc6ce 100644
--- a/telepathy-glib/text-channel.c
+++ b/telepathy-glib/text-channel.c
@@ -80,6 +80,9 @@ struct _TpTextChannelPrivate
/* queue of owned TpSignalledMessage */
GQueue *pending_messages;
gboolean got_initial_messages;
+
+ gboolean is_sms_channel;
+ gboolean sms_flash;
};
enum
@@ -88,6 +91,8 @@ enum
PROP_MESSAGE_PART_SUPPORT_FLAGS,
PROP_DELIVERY_REPORTING_SUPPORT,
PROP_MESSAGE_TYPES,
+ PROP_IS_SMS_CHANNEL,
+ PROP_SMS_FLASH,
};
enum /* signals */
@@ -144,6 +149,14 @@ tp_text_channel_get_property (GObject *object,
tp_text_channel_get_message_types (self));
break;
+ case PROP_IS_SMS_CHANNEL:
+ g_value_set_boolean (value, tp_text_channel_is_sms_channel (self));
+ break;
+
+ case PROP_SMS_FLASH:
+ g_value_set_boolean (value, tp_text_channel_get_sms_flash (self));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -335,6 +348,10 @@ tp_text_channel_constructed (GObject *obj)
tp_proxy_get_object_path (self), err->message);
g_error_free (err);
}
+
+ /* SMS */
+ self->priv->sms_flash = tp_asv_get_boolean (props,
+ TP_PROP_CHANNEL_INTERFACE_SMS_FLASH, NULL);
}
static void
@@ -828,8 +845,91 @@ fail:
g_object_unref (result);
}
+static void
+get_sms_channel_cb (TpProxy *proxy,
+ const GValue *value,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ TpTextChannel *self = (TpTextChannel *) proxy;
+ GSimpleAsyncResult *result = user_data;
+
+ if (error != NULL)
+ {
+ DEBUG ("Failed to get SMSChannel property: %s", error->message);
+
+ g_simple_async_result_set_error (result, error->domain, error->code,
+ "Failed to get SMSChannel property: %s", error->message);
+ goto out;
+ }
+
+ if (!G_VALUE_HOLDS (value, G_TYPE_BOOLEAN))
+ {
+ DEBUG ("SMSChannel property is of the wrong type");
+
+ g_simple_async_result_set_error (result, TP_ERRORS, TP_ERROR_CONFUSED,
+ "SMSChannel property is of the wrong type");
+ goto out;
+ }
+
+ self->priv->is_sms_channel = g_value_get_boolean (value);
+
+ /* self->priv->is_sms_channel is set to FALSE by default, so only notify the
+ * property change is it is now set to TRUE. */
+ if (self->priv->is_sms_channel)
+ g_object_notify (G_OBJECT (self), "is-sms-channel");
+
+out:
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+static void
+sms_channel_changed_cb (TpChannel *proxy,
+ gboolean sms,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ TpTextChannel *self = (TpTextChannel *) proxy;
+
+ if (self->priv->is_sms_channel == sms)
+ return;
+
+ self->priv->is_sms_channel = sms;
+ g_object_notify (weak_object, "is-sms-channel");
+}
+
+static void
+tp_text_channel_prepare_sms_async (TpProxy *proxy,
+ const TpProxyFeature *feature,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ GError *error = NULL;
+
+ result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
+ tp_text_channel_prepare_sms_async);
+
+ tp_cli_channel_interface_sms_connect_to_sms_channel_changed (
+ (TpChannel *) proxy, sms_channel_changed_cb, NULL, NULL,
+ G_OBJECT (proxy), &error);
+ if (error != NULL)
+ {
+ WARNING ("Failed to connect to SMS.SMSChannelChanged: %s",
+ error->message);
+ g_error_free (error);
+ }
+
+ tp_cli_dbus_properties_call_get (proxy, -1,
+ TP_IFACE_CHANNEL_INTERFACE_SMS, "SMSChannel",
+ get_sms_channel_cb, result, NULL, G_OBJECT (proxy));
+}
+
enum {
FEAT_PENDING_MESSAGES,
+ FEAT_SMS,
N_FEAT
};
@@ -837,6 +937,7 @@ static const TpProxyFeature *
tp_text_channel_list_features (TpProxyClass *cls G_GNUC_UNUSED)
{
static TpProxyFeature features[N_FEAT + 1] = { { 0 } };
+ static GQuark need_sms[2] = {0, 0};
if (G_LIKELY (features[0].name != 0))
return features;
@@ -846,6 +947,13 @@ tp_text_channel_list_features (TpProxyClass *cls G_GNUC_UNUSED)
features[FEAT_PENDING_MESSAGES].prepare_async =
tp_text_channel_prepare_pending_messages_async;
+ features[FEAT_SMS].name =
+ TP_TEXT_CHANNEL_FEATURE_SMS;
+ features[FEAT_SMS].prepare_async =
+ tp_text_channel_prepare_sms_async;
+ need_sms[0] = TP_IFACE_QUARK_CHANNEL_INTERFACE_SMS;
+ features[FEAT_SMS].interfaces_needed = need_sms;
+
/* assert that the terminator at the end is there */
g_assert (features[N_FEAT].name == 0);
@@ -929,6 +1037,42 @@ tp_text_channel_class_init (TpTextChannelClass *klass)
g_object_class_install_property (gobject_class,
PROP_MESSAGE_TYPES, param_spec);
+ /**
+ * TpTextChannel:is-sms-channel:
+ *
+ * %TRUE if messages sent and received on this channel are transmitted
+ * via SMS.
+ *
+ * This property is not guaranteed to have a meaningful value until
+ * TP_TEXT_CHANNEL_FEATURE_SMS has been prepared.
+ *
+ * Since: 0.15.UNRELEASED
+ */
+ param_spec = g_param_spec_boolean ("is-sms-channel",
+ "is SMS channel",
+ "The SMS.SMSChannel property of the channel",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (gobject_class, PROP_IS_SMS_CHANNEL,
+ param_spec);
+
+ /**
+ * TpTextChannel:sms-flash:
+ *
+ * %TRUE if this channel is exclusively for receiving class 0 SMSes
+ * (and no SMSes can be sent using tp_text_channel_send_message_async()
+ * on this channel). If %FALSE, no incoming class 0 SMSes will appear
+ * on this channel.
+ *
+ * Since: 0.15.UNRELEASED
+ */
+ param_spec = g_param_spec_boolean ("sms-flash",
+ "SMS flash",
+ "The SMS.Flash property of the channel",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (gobject_class, PROP_SMS_FLASH, param_spec);
+
/**
* TpTextChannel::message-received
* @self: the #TpTextChannel
@@ -1535,3 +1679,59 @@ tp_text_channel_supports_message_type (TpTextChannel *self,
return FALSE;
}
+
+/**
+ * TP_TEXT_CHANNEL_FEATURE_SMS:
+ *
+ * Expands to a call to a function that returns a quark representing the
+ * SMS feature of a #TpTextChannel.
+ *
+ * When this feature is prepared, the TpTextChannel:is-sms-channel property
+ * will have a meaningful value and will be updated when needed.
+ *
+ * One can ask for a feature to be prepared using the
+ * tp_proxy_prepare_async() function, and waiting for it to callback.
+ *
+ * Since: 0.15.UNRELEASED
+ */
+GQuark
+tp_text_channel_get_feature_quark_sms (void)
+{
+ return g_quark_from_static_string ("tp-text-channel-feature-sms");
+}
+
+/**
+ * tp_text_channel_is_sms_channel:
+ * @self: a #TpTextChannel
+ *
+ * Return the #TpTextChannel:is-sms-channel property
+ *
+ * Returns: the value of #TpTextChannel:is-sms-channel property
+ *
+ * Since: 0.15.UNRELEASED
+ */
+gboolean
+tp_text_channel_is_sms_channel (TpTextChannel *self)
+{
+ g_return_val_if_fail (TP_IS_TEXT_CHANNEL (self), FALSE);
+
+ return self->priv->is_sms_channel;
+}
+
+/**
+ * tp_text_channel_get_sms_flash:
+ * @self: a #TpTextChannel
+ *
+ * Return the #TpTextChannel:sms-flash property
+ *
+ * Returns: the value of #TpTextChannel:sms-flash property
+ *
+ * Since: 0.15.UNRELEASED
+ */
+gboolean
+tp_text_channel_get_sms_flash (TpTextChannel *self)
+{
+ g_return_val_if_fail (TP_IS_TEXT_CHANNEL (self), FALSE);
+
+ return self->priv->sms_flash;
+}
diff --git a/telepathy-glib/text-channel.h b/telepathy-glib/text-channel.h
index 492cc86f..1ad84c2d 100644
--- a/telepathy-glib/text-channel.h
+++ b/telepathy-glib/text-channel.h
@@ -119,6 +119,14 @@ gboolean tp_text_channel_set_chat_state_finish (TpTextChannel *self,
GAsyncResult *result,
GError **error);
+#define TP_TEXT_CHANNEL_FEATURE_SMS \
+ tp_text_channel_get_feature_quark_sms ()
+GQuark tp_text_channel_get_feature_quark_sms (void) G_GNUC_CONST;
+
+gboolean tp_text_channel_is_sms_channel (TpTextChannel *self);
+
+gboolean tp_text_channel_get_sms_flash (TpTextChannel *self);
+
G_END_DECLS
#endif
diff --git a/tests/dbus/text-channel.c b/tests/dbus/text-channel.c
index 88f6e750..90dc4eb7 100644
--- a/tests/dbus/text-channel.c
+++ b/tests/dbus/text-channel.c
@@ -23,11 +23,13 @@ typedef struct {
/* Service side objects */
TpBaseConnection *base_connection;
ExampleEcho2Channel *chan_service;
+ ExampleEcho2Channel *sms_chan_service;
TpHandleRepoIface *contact_repo;
/* Client side objects */
TpConnection *connection;
TpTextChannel *channel;
+ TpTextChannel *sms_channel;
TpMessage *received_msg;
TpMessage *removed_msg;
@@ -48,6 +50,7 @@ create_contact_chan (Test *test)
GHashTable *props;
tp_clear_object (&test->chan_service);
+ tp_clear_object (&test->sms_chan_service);
/* Create service-side tube channel object */
chan_path = g_strdup_printf ("%s/Channel",
@@ -81,9 +84,32 @@ create_contact_chan (Test *test)
g_assert_no_error (test->error);
g_free (chan_path);
+ g_hash_table_unref (props);
- tp_handle_unref (test->contact_repo, handle);
+ /* Register channel implementing SMS */
+ chan_path = g_strdup_printf ("%s/ChannelSMS",
+ tp_proxy_get_object_path (test->connection));
+
+ test->sms_chan_service = g_object_new (
+ EXAMPLE_TYPE_ECHO_2_CHANNEL,
+ "connection", test->base_connection,
+ "handle", handle,
+ "object-path", chan_path,
+ "sms", TRUE,
+ NULL);
+
+ g_object_get (test->chan_service,
+ "channel-properties", &props,
+ NULL);
+
+ test->sms_channel = tp_text_channel_new (test->connection, chan_path,
+ props, &test->error);
+ g_assert_no_error (test->error);
+
+ g_free (chan_path);
g_hash_table_unref (props);
+
+ tp_handle_unref (test->contact_repo, handle);
}
static void
@@ -113,6 +139,7 @@ teardown (Test *test,
test->mainloop = NULL;
tp_clear_object (&test->chan_service);
+ tp_clear_object (&test->sms_chan_service);
tp_cli_connection_run_disconnect (test->connection, -1, &test->error, NULL);
g_assert_no_error (test->error);
@@ -127,6 +154,7 @@ teardown (Test *test,
tp_clear_pointer (&test->sent_token, g_free);
tp_clear_object (&test->channel);
+ tp_clear_object (&test->sms_channel);
}
static void
@@ -600,6 +628,62 @@ test_message_sent (Test *test,
g_assert (test->sent_token == NULL);
}
+static void
+notify_cb (GObject *object,
+ GParamSpec *spec,
+ Test *test)
+{
+ test->wait--;
+ if (test->wait <= 0)
+ g_main_loop_quit (test->mainloop);
+}
+
+
+static void
+test_sms_feature (Test *test,
+ gconstpointer data G_GNUC_UNUSED)
+{
+ gboolean is_sms;
+ GQuark features[] = { TP_TEXT_CHANNEL_FEATURE_SMS, 0 };
+
+ g_assert (tp_text_channel_get_sms_flash (test->sms_channel));
+
+ /* SMS feature is not prepared yet */
+ g_assert (!tp_text_channel_is_sms_channel (test->sms_channel));
+
+ g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL);
+ g_assert (!is_sms);
+
+ test->wait++;
+ tp_proxy_prepare_async (test->sms_channel, features,
+ proxy_prepare_cb, test);
+
+ test->wait++;
+ g_signal_connect (test->sms_channel, "notify::is-sms-channel",
+ G_CALLBACK (notify_cb), test);
+
+ g_main_loop_run (test->mainloop);
+ g_assert_no_error (test->error);
+
+ /* Feature has been prepared */
+ g_assert (tp_text_channel_is_sms_channel (test->sms_channel));
+
+ g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL);
+ g_assert (is_sms);
+
+ /* Property is changed */
+ example_echo_2_channel_set_sms (test->sms_chan_service, FALSE);
+
+ test->wait++;
+ g_main_loop_run (test->mainloop);
+ g_assert_no_error (test->error);
+
+ g_assert (!tp_text_channel_is_sms_channel (test->sms_channel));
+
+ g_object_get (test->sms_channel, "is-sms-channel", &is_sms, NULL);
+ g_assert (!is_sms);
+}
+
int
main (int argc,
char **argv)
@@ -621,6 +705,8 @@ main (int argc,
test_ack_message, teardown);
g_test_add ("/text-channel/message-sent", Test, NULL, setup,
test_message_sent, teardown);
+ g_test_add ("/text-channel/sms-feature", Test, NULL, setup,
+ test_sms_feature, teardown);
return g_test_run ();
}