]> git.0d.be Git - empathy.git/blob - src/empathy-streamed-media-factory.c
Update Simplified Chinese help 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
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <telepathy-glib/account-channel-request.h>
26 #include <telepathy-glib/simple-handler.h>
27 #include <telepathy-glib/interfaces.h>
28 #include <telepathy-glib/util.h>
29
30 #include <libempathy/empathy-request-util.h>
31 #include <libempathy/empathy-utils.h>
32
33 #include "empathy-streamed-media-factory.h"
34 #include "empathy-streamed-media-handler.h"
35 #include "src-marshal.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   TpDBusDaemon *dbus;
76   GError *error = NULL;
77
78   obj->priv = priv;
79
80   dbus = tp_dbus_daemon_dup (&error);
81   if (dbus == NULL)
82     {
83       g_warning ("Failed to get TpDBusDaemon: %s", error->message);
84       g_error_free (error);
85       return;
86     }
87
88   priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE,
89       EMPATHY_AV_BUS_NAME_SUFFIX, FALSE, handle_channels_cb, obj, NULL);
90
91   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
92         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
93           TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
94         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
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_AUDIO, G_TYPE_BOOLEAN, TRUE,
102         NULL));
103
104   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
105         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
106           TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
107         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
108         TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, G_TYPE_BOOLEAN, TRUE,
109         NULL));
110
111   tp_base_client_add_handler_capabilities_varargs (priv->handler,
112     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/ice-udp",
113     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/gtalk-p2p",
114     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/video/h264",
115     NULL);
116
117   g_object_unref (dbus);
118 }
119
120 static GObject *
121 empathy_streamed_media_factory_constructor (GType type, guint n_construct_params,
122   GObjectConstructParam *construct_params)
123 {
124   g_return_val_if_fail (call_factory == NULL, NULL);
125
126   call_factory = G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->constructor
127           (type, n_construct_params, construct_params);
128   g_object_add_weak_pointer (call_factory, (gpointer)&call_factory);
129
130   return call_factory;
131 }
132
133 static void
134 empathy_streamed_media_factory_finalize (GObject *object)
135 {
136   /* free any data held directly by the object here */
137
138   if (G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->finalize)
139     G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->finalize (object);
140 }
141
142 static void
143 empathy_streamed_media_factory_dispose (GObject *object)
144 {
145   EmpathyStreamedMediaFactoryPriv *priv = GET_PRIV (object);
146
147   if (priv->dispose_has_run)
148     return;
149
150   priv->dispose_has_run = TRUE;
151
152   tp_clear_object (&priv->handler);
153
154   if (G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->dispose)
155     G_OBJECT_CLASS (empathy_streamed_media_factory_parent_class)->dispose (object);
156 }
157
158 static void
159 empathy_streamed_media_factory_class_init (
160   EmpathyStreamedMediaFactoryClass *empathy_streamed_media_factory_class)
161 {
162   GObjectClass *object_class = G_OBJECT_CLASS (empathy_streamed_media_factory_class);
163
164   g_type_class_add_private (empathy_streamed_media_factory_class,
165     sizeof (EmpathyStreamedMediaFactoryPriv));
166
167   object_class->constructor = empathy_streamed_media_factory_constructor;
168   object_class->dispose = empathy_streamed_media_factory_dispose;
169   object_class->finalize = empathy_streamed_media_factory_finalize;
170
171   signals[NEW_STREAMED_MEDIA_HANDLER] =
172     g_signal_new ("new-streamed-media-handler",
173       G_TYPE_FROM_CLASS (empathy_streamed_media_factory_class),
174       G_SIGNAL_RUN_LAST, 0,
175       NULL, NULL,
176       _src_marshal_VOID__OBJECT_BOOLEAN,
177       G_TYPE_NONE,
178       2, EMPATHY_TYPE_STREAMED_MEDIA_HANDLER, G_TYPE_BOOLEAN);
179 }
180
181 EmpathyStreamedMediaFactory *
182 empathy_streamed_media_factory_initialise (void)
183 {
184   g_return_val_if_fail (call_factory == NULL, NULL);
185
186   return EMPATHY_STREAMED_MEDIA_FACTORY (g_object_new (EMPATHY_TYPE_STREAMED_MEDIA_FACTORY, NULL));
187 }
188
189 EmpathyStreamedMediaFactory *
190 empathy_streamed_media_factory_get (void)
191 {
192   g_return_val_if_fail (call_factory != NULL, NULL);
193
194   return EMPATHY_STREAMED_MEDIA_FACTORY (call_factory);
195 }
196
197 static void
198 create_streamed_media_handler (EmpathyStreamedMediaFactory *factory,
199   EmpathyTpStreamedMedia *call)
200 {
201   EmpathyStreamedMediaHandler *handler;
202
203   g_return_if_fail (factory != NULL);
204
205   handler = empathy_streamed_media_handler_new_for_channel (call);
206
207   g_signal_emit (factory, signals[NEW_STREAMED_MEDIA_HANDLER], 0,
208     handler, FALSE);
209
210   g_object_unref (handler);
211 }
212
213 static void
214 call_status_changed_cb (EmpathyTpStreamedMedia *call,
215     GParamSpec *spec,
216     EmpathyStreamedMediaFactory *self)
217 {
218   if (empathy_tp_streamed_media_get_status (call) <= EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING)
219     return;
220
221   create_streamed_media_handler (self, call);
222
223   g_signal_handlers_disconnect_by_func (call, call_status_changed_cb, self);
224   g_object_unref (call);
225 }
226
227 static void
228 handle_channels_cb (TpSimpleHandler *handler,
229     TpAccount *account,
230     TpConnection *connection,
231     GList *channels,
232     GList *requests_satisfied,
233     gint64 user_action_time,
234     TpHandleChannelsContext *context,
235     gpointer user_data)
236 {
237   EmpathyStreamedMediaFactory *self = user_data;
238   GList *l;
239
240   for (l = channels; l != NULL; l = g_list_next (l))
241     {
242       TpChannel *channel = l->data;
243       EmpathyTpStreamedMedia *call;
244
245       if (tp_proxy_get_invalidated (channel) != NULL)
246         continue;
247
248       if (tp_channel_get_channel_type_id (channel) !=
249           TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
250         continue;
251
252       call = empathy_tp_streamed_media_new (account, channel);
253
254       if (empathy_tp_streamed_media_get_status (call) <= EMPATHY_TP_STREAMED_MEDIA_STATUS_READYING)
255         {
256           /* We have to wait that the TpStreamedMedia is ready as the
257            * call-handler rely on it. */
258           tp_g_signal_connect_object (call, "notify::status",
259               G_CALLBACK (call_status_changed_cb), self, 0);
260           continue;
261         }
262
263       create_streamed_media_handler (self, call);
264       g_object_unref (call);
265     }
266
267   tp_handle_channels_context_accept (context);
268 }
269
270 gboolean
271 empathy_streamed_media_factory_register (EmpathyStreamedMediaFactory *self,
272     GError **error)
273 {
274   EmpathyStreamedMediaFactoryPriv *priv = GET_PRIV (self);
275
276   return tp_base_client_register (priv->handler, error);
277 }