1 /*
2  * Farstream - Farstream Stream Transmitter
3  *
4  * Copyright 2007 Collabora Ltd.
5  *  @author: Olivier Crete <olivier.crete@collabora.co.uk>
6  * Copyright 2007 Nokia Corp.
7  *
8  * fs-stream-transmitter.c - A Farstream Stream Transmitter gobject
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
23  */
24 
25 /**
26  * SECTION:fs-stream-transmitter
27  * @short_description: A stream transmitter object used to convey per-stream
28  *   information to a transmitter.
29  *
30  * This object is the base implementation of a Farstream Stream Transmitter.
31  * It needs to be derived and implement by a Farstream transmitter.
32  * A Farstream Stream transmitter is used to convery per-stream information
33  * to a transmitter, this is mostly local and remote candidates
34  *
35  */
36 
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 
41 #include "fs-stream-transmitter.h"
42 
43 #include <gst/gst.h>
44 
45 #include "fs-conference.h"
46 #include "fs-private.h"
47 
48 #define GST_CAT_DEFAULT _fs_conference_debug
49 
50 /* Signals */
51 enum
52 {
53   ERROR_SIGNAL,
54   NEW_LOCAL_CANDIDATE,
55   NEW_ACTIVE_CANDIDATE_PAIR,
56   LOCAL_CANDIDATES_PREPARED,
57   KNOWN_SOURCE_PACKET_RECEIVED,
58   STATE_CHANGED,
59   LAST_SIGNAL
60 };
61 
62 /* props */
63 enum
64 {
65   PROP_0,
66   PROP_SENDING,
67   PROP_PREFERRED_LOCAL_CANDIDATES,
68   PROP_ASSOCIATE_ON_SOURCE
69 };
70 
71 struct _FsStreamTransmitterPrivate
72 {
73   gboolean disposed;
74 };
75 
76 G_DEFINE_ABSTRACT_TYPE(FsStreamTransmitter, fs_stream_transmitter,
77     G_TYPE_OBJECT);
78 
79 
80 #define FS_STREAM_TRANSMITTER_GET_PRIVATE(o)  \
81   (G_TYPE_INSTANCE_GET_PRIVATE ((o), FS_TYPE_STREAM_TRANSMITTER, \
82                                 FsStreamTransmitterPrivate))
83 
84 static void fs_stream_transmitter_get_property (GObject *object,
85                                                 guint prop_id,
86                                                 GValue *value,
87                                                 GParamSpec *pspec);
88 static void fs_stream_transmitter_set_property (GObject *object,
89                                                 guint prop_id,
90                                                 const GValue *value,
91                                                 GParamSpec *pspec);
92 
93 static guint signals[LAST_SIGNAL] = { 0 };
94 
95 static void
fs_stream_transmitter_class_init(FsStreamTransmitterClass * klass)96 fs_stream_transmitter_class_init (FsStreamTransmitterClass *klass)
97 {
98   GObjectClass *gobject_class;
99 
100   gobject_class = (GObjectClass *) klass;
101 
102   gobject_class->set_property = fs_stream_transmitter_set_property;
103   gobject_class->get_property = fs_stream_transmitter_get_property;
104 
105 
106   /**
107    * FsStreamTransmitter:sending:
108    *
109    * A network source #GstElement to be used by the #FsSession
110    *
111    */
112   g_object_class_install_property (gobject_class,
113       PROP_SENDING,
114       g_param_spec_boolean ("sending",
115         "Whether to send from this transmitter",
116         "If set to FALSE, the transmitter will stop sending to this person",
117         TRUE,
118         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
119 
120   /**
121    * FsStreamTransmitter:preferred-local-candidate:
122    *
123    * The list of preferred local candidates for this stream
124    * It is a #GList of #FsCandidates
125    *
126    */
127   g_object_class_install_property (gobject_class,
128       PROP_PREFERRED_LOCAL_CANDIDATES,
129       g_param_spec_boxed ("preferred-local-candidates",
130         "The preferred candidates",
131         "A GList of FsCandidates",
132         FS_TYPE_CANDIDATE_LIST,
133         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
134 
135   /**
136    * FsStreamTransmitter:associate-on-source:
137    *
138    * This tells the stream transmitter to associate incoming data with this
139    * based on the source without looking at the content if possible.
140    *
141    */
142 
143   g_object_class_install_property (gobject_class,
144       PROP_ASSOCIATE_ON_SOURCE,
145       g_param_spec_boolean ("associate-on-source",
146         "Associate incoming data based on the source address",
147         "Whether to associate incoming data stream based on the source address",
148         TRUE,
149         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
150 
151   /**
152    * FsStreamTransmitter::error:
153    * @self: #FsStreamTransmitter that emitted the signal
154    * @errorno: The number of the error
155    * @error_msg: Error message (for the programmer)
156    *
157    * This signal is emitted in any error condition
158    *
159    */
160   signals[ERROR_SIGNAL] = g_signal_new ("error",
161       G_TYPE_FROM_CLASS (klass),
162       G_SIGNAL_RUN_LAST,
163       0, NULL, NULL, NULL,
164       G_TYPE_NONE, 2, FS_TYPE_ERROR, G_TYPE_STRING);
165 
166     /**
167    * FsStreamTransmitter::new-active-candidate-pair:
168    * @self: #FsStreamTransmitter that emitted the signal
169    * @local_candidate: #FsCandidate of the local candidate being used
170    * @remote_candidate: #FsCandidate of the remote candidate being used
171    *
172    * This signal is emitted when there is a new active chandidate pair that has
173    * been established. This is specially useful for ICE where the active
174    * candidate pair can change automatically due to network conditions. The user
175    * must not modify the candidates and must copy them if he wants to use them
176    * outside the callback scope.
177    *
178    */
179   signals[NEW_ACTIVE_CANDIDATE_PAIR] = g_signal_new
180     ("new-active-candidate-pair",
181         G_TYPE_FROM_CLASS (klass),
182         G_SIGNAL_RUN_LAST,
183         0, NULL, NULL, NULL,
184         G_TYPE_NONE, 2, FS_TYPE_CANDIDATE, FS_TYPE_CANDIDATE);
185 
186  /**
187    * FsStreamTransmitter::new-local-candidate:
188    * @self: #FsStream that emitted the signal
189    * @local_candidate: #FsCandidate of the local candidate
190    *
191    * This signal is emitted when a new local candidate is discovered.
192    *
193    */
194   signals[NEW_LOCAL_CANDIDATE] = g_signal_new
195     ("new-local-candidate",
196       G_TYPE_FROM_CLASS (klass),
197       G_SIGNAL_RUN_LAST,
198       0,
199       NULL,
200       NULL,
201       g_cclosure_marshal_VOID__BOXED,
202       G_TYPE_NONE, 1, FS_TYPE_CANDIDATE);
203 
204  /**
205    * FsStreamTransmitter::local-candidates-prepared:
206    * @self: #FsStreamTransmitter that emitted the signal
207    *
208    * This signal is emitted when all local candidates have been
209    * prepared, an ICE implementation would send its SDP offer or answer.
210    *
211    */
212   signals[LOCAL_CANDIDATES_PREPARED] = g_signal_new
213     ("local-candidates-prepared",
214       G_TYPE_FROM_CLASS (klass),
215       G_SIGNAL_RUN_LAST,
216       0,
217       NULL,
218       NULL,
219       g_cclosure_marshal_VOID__VOID,
220       G_TYPE_NONE, 0);
221 
222  /**
223    * FsStreamTransmitter::known-source-packet-received:
224    * @self: #FsStreamTransmitter that emitted the signal
225    * @component: The Component on which this buffer was received
226    * @buffer: the #GstBuffer coming from the known source
227    *
228    * This signal is emitted when a buffer coming from a confirmed known source
229    * is received.
230    */
231   signals[KNOWN_SOURCE_PACKET_RECEIVED] = g_signal_new
232     ("known-source-packet-received",
233       G_TYPE_FROM_CLASS (klass),
234       G_SIGNAL_RUN_LAST,
235       0, NULL, NULL, NULL,
236       G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER);
237 
238 
239   /**
240    * FsStreamTransmitter::state-changed:
241    * @self: #FsStreamTransmitter that emitted the signal
242    * @component: the id of the component which state has changed
243    * @state: the new state of the component
244    *
245    * This signal is emitted when the ICE state (or equivalent) of the component
246    * changes
247    */
248  signals[STATE_CHANGED] = g_signal_new
249     ("state-changed",
250       G_TYPE_FROM_CLASS (klass),
251       G_SIGNAL_RUN_LAST,
252       0, NULL, NULL, NULL,
253       G_TYPE_NONE, 2, G_TYPE_UINT, FS_TYPE_STREAM_STATE);
254 
255 
256   g_type_class_add_private (klass, sizeof (FsStreamTransmitterPrivate));
257 }
258 
259 static void
fs_stream_transmitter_init(FsStreamTransmitter * self)260 fs_stream_transmitter_init (FsStreamTransmitter *self)
261 {
262   /* member init */
263   self->priv = FS_STREAM_TRANSMITTER_GET_PRIVATE (self);
264   self->priv->disposed = FALSE;
265 }
266 
267 static void
fs_stream_transmitter_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)268 fs_stream_transmitter_get_property (GObject *object,
269                                     guint prop_id,
270                                     GValue *value,
271                                     GParamSpec *pspec)
272 {
273   GST_WARNING ("Subclass %s of FsStreamTransmitter does not override the %s"
274       " property getter",
275       G_OBJECT_TYPE_NAME(object),
276       g_param_spec_get_name (pspec));
277 }
278 
279 static void
fs_stream_transmitter_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)280 fs_stream_transmitter_set_property (GObject *object,
281                                     guint prop_id,
282                                     const GValue *value,
283                                     GParamSpec *pspec)
284 {
285   switch (prop_id)
286   {
287     /* These properties, we can safely not override */
288     case PROP_ASSOCIATE_ON_SOURCE:
289       break;
290     default:
291       GST_WARNING ("Subclass %s of FsStreamTransmitter does not override the %s"
292           " property setter",
293           G_OBJECT_TYPE_NAME(object),
294           g_param_spec_get_name (pspec));
295       break;
296   }
297 }
298 
299 
300 /**
301  * fs_stream_transmitter_add_remote_candidates:
302  * @streamtransmitter: a #FsStreamTranmitter
303  * @candidates: (element-type FsCandidate): a #GList of the remote candidates
304  * @error: location of a #GError, or NULL if no error occured
305  *
306  * This function is used to add remote candidates to the transmitter
307  *
308  * Returns: TRUE of the candidate could be added, FALSE if it couldnt
309  *   (and the #GError will be set)
310  */
311 
312 gboolean
fs_stream_transmitter_add_remote_candidates(FsStreamTransmitter * streamtransmitter,GList * candidates,GError ** error)313 fs_stream_transmitter_add_remote_candidates (
314     FsStreamTransmitter *streamtransmitter,
315     GList *candidates,
316     GError **error)
317 {
318   FsStreamTransmitterClass *klass;
319 
320   g_return_val_if_fail (streamtransmitter, FALSE);
321   g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE);
322   klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter);
323 
324   if (klass->add_remote_candidates) {
325     return klass->add_remote_candidates (streamtransmitter, candidates, error);
326   } else {
327     g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED,
328       "add_remote_candidate not defined in stream transmitter class");
329   }
330 
331   return FALSE;
332 }
333 
334 /**
335  * fs_stream_transmitter_force_remote_candidates:
336  * @streamtransmitter: a #FsStreamTransmitter
337  * @remote_candidates: (element-type FsCandidate): a #GList of #FsCandidate to
338  *   force
339  * @error: location of a #GError, or NULL if no error occured
340  *
341  * This function forces data to be sent immediately to the selected remote
342  * candidate, by-passing any connectivity checks. There should be at most
343  * one candidate per component.
344  *
345  * Returns: %TRUE if the candidates could be forced, %FALSE otherwise
346  */
347 
348 gboolean
fs_stream_transmitter_force_remote_candidates(FsStreamTransmitter * streamtransmitter,GList * remote_candidates,GError ** error)349 fs_stream_transmitter_force_remote_candidates (
350     FsStreamTransmitter *streamtransmitter,
351     GList *remote_candidates,
352     GError **error)
353 {
354   FsStreamTransmitterClass *klass;
355 
356   g_return_val_if_fail (streamtransmitter, FALSE);
357   g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE);
358   klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter);
359 
360   if (klass->force_remote_candidates) {
361     return klass->force_remote_candidates (streamtransmitter,
362         remote_candidates, error);
363   } else {
364     g_set_error (error, FS_ERROR, FS_ERROR_NOT_IMPLEMENTED,
365       "force_remote_candidates not defined in stream transmitter class");
366   }
367 
368   return FALSE;
369 }
370 
371 /**
372  * fs_stream_transmitter_gather_local_candidates:
373  * @streamtransmitter: a #FsStreamTransmitter
374  * @error: location of a #GErrorh, or NULL if no error occured
375  *
376  * This function tells the transmitter to start gathering local candidates,
377  * signals for new candidates and newly active candidates can be emitted
378  * during the call to this function.
379  *
380  * Returns: %TRUE if it succeeds (or is not implemented), %FALSE otherwise
381  */
382 
383 gboolean
fs_stream_transmitter_gather_local_candidates(FsStreamTransmitter * streamtransmitter,GError ** error)384 fs_stream_transmitter_gather_local_candidates (
385     FsStreamTransmitter *streamtransmitter,
386     GError **error)
387 {
388   FsStreamTransmitterClass *klass;
389 
390   g_return_val_if_fail (streamtransmitter, FALSE);
391   g_return_val_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter), FALSE);
392   klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter);
393 
394   if (klass->gather_local_candidates)
395     return klass->gather_local_candidates (streamtransmitter, error);
396   else
397     return TRUE;
398 }
399 
400 
401 
402 /**
403  * fs_stream_transmitter_stop:
404  * @streamtransmitter: a #FsStreamTransmitter
405  *
406  * This functions stops the #FsStreamTransmitter, it must be called before
407  * the last reference is dropped.
408  */
409 
410 void
fs_stream_transmitter_stop(FsStreamTransmitter * streamtransmitter)411 fs_stream_transmitter_stop (FsStreamTransmitter *streamtransmitter)
412 {
413   FsStreamTransmitterClass *klass;
414 
415   g_return_if_fail (streamtransmitter);
416   g_return_if_fail (FS_IS_STREAM_TRANSMITTER (streamtransmitter));
417   klass = FS_STREAM_TRANSMITTER_GET_CLASS (streamtransmitter);
418 
419   if (klass->stop)
420     klass->stop (streamtransmitter);
421 }
422 
423 
424 /**
425  * fs_stream_transmitter_emit_error:
426  * @streamtransmitter: #FsStreamTransmitter on which to emit the error signal
427  * @error_no: The number of the error
428  * @error_msg: Error message (for the programmer)
429  *
430  * This function emit the "error" signal on a #FsStreamTransmitter, it should
431  * only be called by subclasses.
432  */
433 void
fs_stream_transmitter_emit_error(FsStreamTransmitter * streamtransmitter,gint error_no,const gchar * error_msg)434 fs_stream_transmitter_emit_error (FsStreamTransmitter *streamtransmitter,
435     gint error_no,
436     const gchar *error_msg)
437 {
438   g_signal_emit (streamtransmitter, signals[ERROR_SIGNAL], 0, error_no,
439       error_msg);
440 }
441