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