]> git.0d.be Git - empathy.git/blob - src/empathy-streamed-media-factory.c
Updated Belarusian translation.
[empathy.git] / src / empathy-streamed-media-factory.c
1 /*
2  * empathy-streamed-media-factory.c - Source for EmpathyStreamedMediaFactory
3  * Copyright (C) 2008-2011 Collabora Ltd.
4  * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include <telepathy-glib/account-channel-request.h>
27 #include <telepathy-glib/simple-handler.h>
28 #include <telepathy-glib/interfaces.h>
29 #include <telepathy-glib/util.h>
30
31 #include <libempathy/empathy-request-util.h>
32 #include <libempathy/empathy-utils.h>
33
34 #include "empathy-streamed-media-factory.h"
35 #include "empathy-streamed-media-handler.h"
36
37 #define DEBUG_FLAG EMPATHY_DEBUG_VOIP
38 #include <libempathy/empathy-debug.h>
39
40 G_DEFINE_TYPE(EmpathyStreamedMediaFactory, empathy_streamed_media_factory, G_TYPE_OBJECT)
41
42 static void handle_channels_cb (TpSimpleHandler *handler,
43     TpAccount *account,
44     TpConnection *connection,
45     GList *channels,
46     GList *requests_satisfied,
47     gint64 user_action_time,
48     TpHandleChannelsContext *context,
49     gpointer user_data);
50
51 /* signal enum */
52 enum
53 {
54     NEW_STREAMED_MEDIA_HANDLER,
55     LAST_SIGNAL
56 };
57
58 static guint signals[LAST_SIGNAL] = {0};
59
60 /* private structure */
61 typedef struct {
62   TpBaseClient *handler;
63   gboolean dispose_has_run;
64 } EmpathyStreamedMediaFactoryPriv;
65
66 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyStreamedMediaFactory)
67
68 static GObject *call_factory = NULL;
69
70 static void
71 empathy_streamed_media_factory_init (EmpathyStreamedMediaFactory *obj)
72 {
73   EmpathyStreamedMediaFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj,
74     EMPATHY_TYPE_STREAMED_MEDIA_FACTORY, EmpathyStreamedMediaFactoryPriv);
75   TpAccountManager *am;
76
77   obj->priv = priv;
78
79   am = tp_account_manager_dup ();
80
81   priv->handler = tp_simple_handler_new_with_am (am, FALSE, FALSE,
82       EMPATHY_AV_BUS_NAME_SUFFIX, FALSE, handle_channels_cb, obj, NULL);
83
84   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
85         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
86           TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
87         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
88         NULL));
89
90   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
91         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
92           TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
93         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
94         TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, G_TYPE_BOOLEAN, TRUE,
95         NULL));
96
97   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
98         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
99           TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
100         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
101         TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, G_TYPE_BOOLEAN, TRUE,
102         NULL));
103
104   tp_base_client_add_handler_capabilities_varargs (priv->handler,
105     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/ice-udp",
106     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/gtalk-p2p",
107     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/video/h264",
108     NULL);
109
110   g_object_unref (am);
111 }
112
113 static GObject *
114 empathy_streamed_media_factory_constructor (GType type, guint n_construct_params,
115   GObjectConstructParam *construct_params)
116 {
117   g_return_val_if_fail (call_factory == NULL, NULL);
118
119   call_factory = G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->constructor
120           (type, n_construct_params, construct_params);
121   g_object_add_weak_pointer (call_factory, (gpointer)&call_factory);
122
123   return call_factory;
124 }
125
126 static void
127 empathy_streamed_media_factory_finalize (GObject *object)
128 {
129   /* free any data held directly by the object here */
130
131   if (G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->finalize)
132     G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->finalize (object);
133 }
134
135 static void
136 empathy_streamed_media_factory_dispose (GObject *object)
137 {
138   EmpathyStreamedMediaFactoryPriv *priv = GET_PRIV (object);
139
140   if (priv->dispose_has_run)
141     return;
142
143   priv->dispose_has_run = TRUE;
144
145   tp_clear_object (&priv->handler);
146
147   if (G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->dispose)
148     G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->dispose (object);
149 }
150
151 static void
152 empathy_streamed_media_factory_class_init (
153   EmpathyStreamedMediaFactoryClass *empathy_streamed_media_factory_class)
154 {
155   GObjectClass *object_class = G_OBJECT_CLASS (empathy_streamed_media_factory_class);
156
157   g_type_class_add_private (empathy_streamed_media_factory_class,
158     sizeof (EmpathyStreamedMediaFactoryPriv));
159
160   object_class->constructor = empathy_streamed_media_factory_constructor;
161   object_class->dispose = empathy_streamed_media_factory_dispose;
162   object_class->finalize = empathy_streamed_media_factory_finalize;
163
164   signals[NEW_STREAMED_MEDIA_HANDLER] =
165     g_signal_new ("new-streamed-media-handler",
166       G_TYPE_FROM_CLASS (empathy_streamed_media_factory_class),
167       G_SIGNAL_RUN_LAST, 0,
168       NULL, NULL,
169       g_cclosure_marshal_generic,
170       G_TYPE_NONE,
171       2, EMPATHY_TYPE_STREAMED_MEDIA_HANDLER, G_TYPE_BOOLEAN);
172 }
173
174 EmpathyStreamedMediaFactory *
175 empathy_streamed_media_factory_initialise (void)
176 {
177   g_return_val_if_fail (call_factory == NULL, NULL);
178
179   return EMPATHY_STREAMED_MEDIA_FACTORY (g_object_new (EMPATHY_TYPE_STREAMED_MEDIA_FACTORY, NULL));
180 }
181
182 EmpathyStreamedMediaFactory *
183 empathy_streamed_media_factory_get (void)
184 {
185   g_return_val_if_fail (call_factory != NULL, NULL);
186
187   return EMPATHY_STREAMED_MEDIA_FACTORY (call_factory);
188 }
189
190 static void
191 create_streamed_media_handler (EmpathyStreamedMediaFactory *factory,
192   EmpathyTpStreamedMedia *call)
193 {
194   EmpathyStreamedMediaHandler *handler;
195
196   g_return_if_fail (factory != NULL);
197
198   handler = empathy_streamed_media_handler_new_for_channel (call);
199
200   g_signal_emit (factory, signals[NEW_STREAMED_MEDIA_HANDLER], 0,
201     handler, FALSE);
202
203   g_object_unref (handler);
204 }
205
206 static void
207 call_status_changed_cb (EmpathyTpStreamedMedia *call,
208     GParamSpec *spec,
209     EmpathyStreamedMediaFactory *self)
210 {
211   if (empathy_tp_streamed_media_get_status (call) <= EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING)
212     return;
213
214   create_streamed_media_handler (self, call);
215
216   g_signal_handlers_disconnect_by_func (call, call_status_changed_cb, self);
217   g_object_unref (call);
218 }
219
220 static void
221 handle_channels_cb (TpSimpleHandler *handler,
222     TpAccount *account,
223     TpConnection *connection,
224     GList *channels,
225     GList *requests_satisfied,
226     gint64 user_action_time,
227     TpHandleChannelsContext *context,
228     gpointer user_data)
229 {
230   EmpathyStreamedMediaFactory *self = user_data;
231   GList *l;
232
233   for (l = channels; l != NULL; l = g_list_next (l))
234     {
235       TpChannel *channel = l->data;
236       EmpathyTpStreamedMedia *call;
237
238       if (tp_proxy_get_invalidated (channel) != NULL)
239         continue;
240
241       if (tp_channel_get_channel_type_id (channel) !=
242           TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
243         continue;
244
245       call = empathy_tp_streamed_media_new (account, channel);
246
247       if (empathy_tp_streamed_media_get_status (call) <= EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING)
248         {
249           /* We have to wait that the TpStreamedMedia is ready as the
250            * call-handler rely on it. */
251           tp_g_signal_connect_object (call, "notify::status",
252               G_CALLBACK (call_status_changed_cb), self, 0);
253           continue;
254         }
255
256       create_streamed_media_handler (self, call);
257       g_object_unref (call);
258     }
259
260   tp_handle_channels_context_accept (context);
261 }
262
263 gboolean
264 empathy_streamed_media_factory_register (EmpathyStreamedMediaFactory *self,
265     GError **error)
266 {
267   EmpathyStreamedMediaFactoryPriv *priv = GET_PRIV (self);
268
269   return tp_base_client_register (priv->handler, error);
270 }