2
* call-content-codec-offer.c - Source for TpyCallContentCodecOffer
3
* Copyright (C) 2009 Collabora Ltd.
4
* @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
#include <telepathy-glib/dbus.h>
27
#include <telepathy-glib/dbus-properties-mixin.h>
28
#include <telepathy-glib/svc-properties-interface.h>
30
#include "call-content-codec-offer.h"
31
#include "extensions.h"
33
#define DEBUG_FLAG TPY_DEBUG_CALL
36
static void call_content_codec_offer_iface_init (gpointer, gpointer);
38
G_DEFINE_TYPE_WITH_CODE(TpyCallContentCodecOffer,
39
tpy_call_content_codec_offer,
41
G_IMPLEMENT_INTERFACE (TPY_TYPE_SVC_CALL_CONTENT_CODEC_OFFER,
42
call_content_codec_offer_iface_init);
43
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
44
tp_dbus_properties_mixin_iface_init);
52
PROP_REMOTE_CONTACT_CODECS,
56
/* private structure */
57
struct _TpyCallContentCodecOfferPrivate
59
gboolean dispose_has_run;
67
GSimpleAsyncResult *result;
68
GCancellable *cancellable;
72
#define TPY_CALL_CONTENT_CODEC_OFFER_GET_PRIVATE(o) \
73
(G_TYPE_INSTANCE_GET_PRIVATE ((o), \
74
TPY_TYPE_CALL_CONTENT_CODEC_OFFER, TpyCallContentCodecOfferPrivate))
77
tpy_call_content_codec_offer_init (TpyCallContentCodecOffer *self)
79
TpyCallContentCodecOfferPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
80
TPY_TYPE_CALL_CONTENT_CODEC_OFFER,
81
TpyCallContentCodecOfferPrivate);
84
priv->bus = tp_dbus_daemon_dup (NULL);
87
static void tpy_call_content_codec_offer_dispose (GObject *object);
88
static void tpy_call_content_codec_offer_finalize (GObject *object);
90
static const gchar *interfaces[] = {
95
tpy_call_content_codec_offer_get_property (GObject *object,
100
TpyCallContentCodecOffer *offer =
101
TPY_CALL_CONTENT_CODEC_OFFER (object);
102
TpyCallContentCodecOfferPrivate *priv = offer->priv;
106
case PROP_OBJECT_PATH:
107
g_value_set_string (value, priv->object_path);
109
case PROP_INTERFACES:
110
g_value_set_boxed (value, interfaces);
112
case PROP_REMOTE_CONTACT_CODECS:
113
g_value_set_boxed (value, priv->codecs);
115
case PROP_REMOTE_CONTACT:
116
g_value_set_uint (value, priv->contact);
119
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
125
tpy_call_content_codec_offer_set_property (GObject *object,
130
TpyCallContentCodecOffer *content =
131
TPY_CALL_CONTENT_CODEC_OFFER (object);
132
TpyCallContentCodecOfferPrivate *priv = content->priv;
136
case PROP_OBJECT_PATH:
137
priv->object_path = g_value_dup_string (value);
138
g_assert (priv->object_path != NULL);
140
case PROP_REMOTE_CONTACT_CODECS:
141
priv->codecs = g_value_dup_boxed (value);
143
case PROP_REMOTE_CONTACT:
144
priv->contact = g_value_get_uint (value);
147
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
153
tpy_call_content_codec_offer_class_init (
154
TpyCallContentCodecOfferClass *tpy_call_content_codec_offer_class)
156
GObjectClass *object_class =
157
G_OBJECT_CLASS (tpy_call_content_codec_offer_class);
160
static TpDBusPropertiesMixinPropImpl codec_offer_props[] = {
161
{ "Interfaces", "interfaces", NULL },
162
{ "RemoteContactCodecs", "remote-contact-codecs", NULL },
163
{ "RemoteContact", "remote-contact", NULL },
167
static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
168
{ TPY_IFACE_CALL_CONTENT_CODEC_OFFER,
169
tp_dbus_properties_mixin_getter_gobject_properties,
177
g_type_class_add_private (tpy_call_content_codec_offer_class,
178
sizeof (TpyCallContentCodecOfferPrivate));
180
object_class->get_property = tpy_call_content_codec_offer_get_property;
181
object_class->set_property = tpy_call_content_codec_offer_set_property;
183
object_class->dispose = tpy_call_content_codec_offer_dispose;
184
object_class->finalize = tpy_call_content_codec_offer_finalize;
186
spec = g_param_spec_string ("object-path", "D-Bus object path",
187
"The D-Bus object path used for this "
188
"object on the bus.",
190
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
191
g_object_class_install_property (object_class, PROP_OBJECT_PATH, spec);
193
spec = g_param_spec_boxed ("interfaces",
195
"Extra interfaces provided by this codec offer",
197
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
198
g_object_class_install_property (object_class, PROP_INTERFACES,
201
spec = g_param_spec_boxed ("remote-contact-codecs",
202
"RemoteContactCodecs",
203
"A list of codecs the remote contact supports",
204
TPY_ARRAY_TYPE_CODEC_LIST,
205
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
206
g_object_class_install_property (object_class, PROP_REMOTE_CONTACT_CODECS,
209
spec = g_param_spec_uint ("remote-contact",
211
"The contact handle that this codec offer applies to",
213
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
214
g_object_class_install_property (object_class, PROP_REMOTE_CONTACT,
217
tpy_call_content_codec_offer_class->dbus_props_class.interfaces
219
tp_dbus_properties_mixin_class_init (object_class,
220
G_STRUCT_OFFSET (TpyCallContentCodecOfferClass, dbus_props_class));
224
tpy_call_content_codec_offer_dispose (GObject *object)
226
TpyCallContentCodecOffer *self = TPY_CALL_CONTENT_CODEC_OFFER (object);
227
TpyCallContentCodecOfferPrivate *priv = self->priv;
229
g_assert (priv->result == NULL);
231
if (priv->dispose_has_run)
234
priv->dispose_has_run = TRUE;
236
if (priv->codecs != NULL)
239
g_boxed_free (TPY_ARRAY_TYPE_CODEC_LIST, priv->codecs);
243
g_object_unref (priv->bus);
246
/* release any references held by the object here */
247
if (G_OBJECT_CLASS (tpy_call_content_codec_offer_parent_class)->dispose)
248
G_OBJECT_CLASS (tpy_call_content_codec_offer_parent_class)->dispose (
253
tpy_call_content_codec_offer_finalize (GObject *object)
255
TpyCallContentCodecOffer *self = TPY_CALL_CONTENT_CODEC_OFFER (object);
256
TpyCallContentCodecOfferPrivate *priv = self->priv;
258
g_free (priv->object_path);
259
/* free any data held directly by the object here */
261
G_OBJECT_CLASS (tpy_call_content_codec_offer_parent_class)->finalize (
266
tpy_call_content_codec_offer_accept (TpySvcCallContentCodecOffer *iface,
267
const GPtrArray *codecs,
268
DBusGMethodInvocation *context)
270
TpyCallContentCodecOffer *self = TPY_CALL_CONTENT_CODEC_OFFER (iface);
271
TpyCallContentCodecOfferPrivate *priv = self->priv;
273
g_return_if_fail (priv->bus != NULL);
275
DEBUG ("%s was accepted", priv->object_path);
277
if (priv->cancellable != NULL)
279
g_cancellable_disconnect (priv->cancellable, priv->handler_id);
280
g_object_unref (priv->cancellable);
281
priv->cancellable = NULL;
282
priv->handler_id = 0;
285
g_simple_async_result_set_op_res_gpointer (priv->result,
286
(gpointer) codecs, NULL);
287
g_simple_async_result_complete (priv->result);
288
g_object_unref (priv->result);
291
tpy_svc_call_content_codec_offer_return_from_accept (context);
293
tp_dbus_daemon_unregister_object (priv->bus, G_OBJECT (self));
297
tpy_call_content_codec_offer_reject (TpySvcCallContentCodecOffer *iface,
298
DBusGMethodInvocation *context)
300
TpyCallContentCodecOffer *self = TPY_CALL_CONTENT_CODEC_OFFER (iface);
301
TpyCallContentCodecOfferPrivate *priv = self->priv;
303
g_return_if_fail (priv->bus != NULL);
305
DEBUG ("%s was rejected", priv->object_path);
307
if (priv->cancellable != NULL)
309
g_cancellable_disconnect (priv->cancellable, priv->handler_id);
310
g_object_unref (priv->cancellable);
311
priv->cancellable = NULL;
312
priv->handler_id = 0;
315
g_simple_async_result_set_error (priv->result,
316
G_IO_ERROR, G_IO_ERROR_FAILED, "Codec offer was rejected");
317
g_simple_async_result_complete (priv->result);
318
g_object_unref (priv->result);
321
tpy_svc_call_content_codec_offer_return_from_reject (context);
323
tp_dbus_daemon_unregister_object (priv->bus, G_OBJECT (self));
327
call_content_codec_offer_iface_init (gpointer iface, gpointer data)
329
TpySvcCallContentCodecOfferClass *klass =
330
(TpySvcCallContentCodecOfferClass *) iface;
332
#define IMPLEMENT(x) tpy_svc_call_content_codec_offer_implement_##x (\
333
klass, tpy_call_content_codec_offer_##x)
339
TpyCallContentCodecOffer *
340
tpy_call_content_codec_offer_new (const gchar *object_path,
341
TpHandle remote_contact,
344
return g_object_new (TPY_TYPE_CALL_CONTENT_CODEC_OFFER,
345
"object-path", object_path,
346
"remote-contact", remote_contact,
347
"remote-contact-codecs", codecs,
352
cancelled_cb (GCancellable *cancellable, gpointer user_data)
354
TpyCallContentCodecOffer *offer = user_data;
355
TpyCallContentCodecOfferPrivate *priv = offer->priv;
357
g_return_if_fail (priv->bus != NULL);
359
tp_dbus_daemon_unregister_object (priv->bus, G_OBJECT (offer));
361
g_simple_async_result_set_error (priv->result,
362
G_IO_ERROR, G_IO_ERROR_CANCELLED, "Offer cancelled");
363
g_simple_async_result_complete_in_idle (priv->result);
365
g_object_unref (priv->cancellable);
366
g_object_unref (priv->result);
368
priv->cancellable = NULL;
369
priv->handler_id = 0;
373
tpy_call_content_codec_offer_offer (TpyCallContentCodecOffer *offer,
374
GCancellable *cancellable,
375
GAsyncReadyCallback callback,
378
TpyCallContentCodecOfferPrivate *priv = offer->priv;
380
g_return_if_fail (priv->bus != NULL);
382
/* FIXME implement cancellable support */
383
if (G_UNLIKELY (priv->result != NULL))
386
priv->result = g_simple_async_result_new (G_OBJECT (offer),
387
callback, user_data, tpy_call_content_codec_offer_offer_finish);
389
/* register object on the bus */
390
DEBUG ("Registering %s", priv->object_path);
391
tp_dbus_daemon_register_object (priv->bus, priv->object_path,
394
if (cancellable != NULL)
396
priv->cancellable = cancellable;
397
priv->handler_id = g_cancellable_connect (
398
cancellable, G_CALLBACK (cancelled_cb), offer, NULL);
404
g_simple_async_report_error_in_idle (G_OBJECT (offer), callback, user_data,
405
G_IO_ERROR, G_IO_ERROR_PENDING, "Another offer operation is pending");
409
tpy_call_content_codec_offer_offer_finish (
410
TpyCallContentCodecOffer *offer,
411
GAsyncResult *result,
414
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
418
g_return_val_if_fail (g_simple_async_result_is_valid (result,
419
G_OBJECT (offer), tpy_call_content_codec_offer_offer_finish),
422
return g_simple_async_result_get_op_res_gpointer (
423
G_SIMPLE_ASYNC_RESULT (result));