~ubuntu-branches/ubuntu/quantal/pidgin/quantal

« back to all changes in this revision

Viewing changes to .pc/70_farstream_rename.patch/libpurple/media.c

  • Committer: Package Import Robot
  • Author(s): Ken VanDine
  • Date: 2012-04-04 17:02:58 UTC
  • Revision ID: package-import@ubuntu.com-20120404170258-m6yhyj8syg6m6fbc
Tags: 1:2.10.2-1ubuntu2
* debian/patches/70_farstream_rename.patch
  - updated patch from the upstream bug report
    http://developer.pidgin.im/ticket/14936

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file media.c Media API
 
3
 * @ingroup core
 
4
 */
 
5
 
 
6
/* purple
 
7
 *
 
8
 * Purple is the legal property of its developers, whose names are too numerous
 
9
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 
10
 * source distribution.
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License as published by
 
14
 * the Free Software Foundation; either version 2 of the License, or
 
15
 * (at your option) any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
25
 */
 
26
#include "internal.h"
 
27
 
 
28
#include "account.h"
 
29
#include "media.h"
 
30
#include "media/backend-iface.h"
 
31
#include "mediamanager.h"
 
32
 
 
33
#include "debug.h"
 
34
 
 
35
#ifdef USE_GSTREAMER
 
36
#include "media/backend-fs2.h"
 
37
#include "marshallers.h"
 
38
#include "media-gst.h"
 
39
#endif
 
40
 
 
41
#ifdef USE_VV
 
42
 
 
43
/** @copydoc _PurpleMediaSession */
 
44
typedef struct _PurpleMediaSession PurpleMediaSession;
 
45
/** @copydoc _PurpleMediaStream */
 
46
typedef struct _PurpleMediaStream PurpleMediaStream;
 
47
/** @copydoc _PurpleMediaClass */
 
48
typedef struct _PurpleMediaClass PurpleMediaClass;
 
49
/** @copydoc _PurpleMediaPrivate */
 
50
typedef struct _PurpleMediaPrivate PurpleMediaPrivate;
 
51
 
 
52
/** The media class */
 
53
struct _PurpleMediaClass
 
54
{
 
55
        GObjectClass parent_class;     /**< The parent class. */
 
56
};
 
57
 
 
58
/** The media class's private data */
 
59
struct _PurpleMedia
 
60
{
 
61
        GObject parent;                /**< The parent of this object. */
 
62
        PurpleMediaPrivate *priv;      /**< The private data of this object. */
 
63
};
 
64
 
 
65
struct _PurpleMediaSession
 
66
{
 
67
        gchar *id;
 
68
        PurpleMedia *media;
 
69
        PurpleMediaSessionType type;
 
70
        gboolean initiator;
 
71
};
 
72
 
 
73
struct _PurpleMediaStream
 
74
{
 
75
        PurpleMediaSession *session;
 
76
        gchar *participant;
 
77
 
 
78
        GList *local_candidates;
 
79
        GList *remote_candidates;
 
80
 
 
81
        gboolean initiator;
 
82
        gboolean accepted;
 
83
        gboolean candidates_prepared;
 
84
 
 
85
        GList *active_local_candidates;
 
86
        GList *active_remote_candidates;
 
87
};
 
88
#endif
 
89
 
 
90
struct _PurpleMediaPrivate
 
91
{
 
92
#ifdef USE_VV
 
93
        PurpleMediaManager *manager;
 
94
        PurpleAccount *account;
 
95
        PurpleMediaBackend *backend;
 
96
        gchar *conference_type;
 
97
        gboolean initiator;
 
98
        gpointer prpl_data;
 
99
 
 
100
        GHashTable *sessions;   /* PurpleMediaSession table */
 
101
        GList *participants;
 
102
        GList *streams;         /* PurpleMediaStream table */
 
103
#else
 
104
        gpointer dummy;
 
105
#endif
 
106
};
 
107
 
 
108
#ifdef USE_VV
 
109
#define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate))
 
110
 
 
111
static void purple_media_class_init (PurpleMediaClass *klass);
 
112
static void purple_media_init (PurpleMedia *media);
 
113
static void purple_media_dispose (GObject *object);
 
114
static void purple_media_finalize (GObject *object);
 
115
static void purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
 
116
static void purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
 
117
 
 
118
static void purple_media_new_local_candidate_cb(PurpleMediaBackend *backend,
 
119
                const gchar *sess_id, const gchar *participant,
 
120
                PurpleMediaCandidate *candidate, PurpleMedia *media);
 
121
static void purple_media_candidates_prepared_cb(PurpleMediaBackend *backend,
 
122
                const gchar *sess_id, const gchar *name, PurpleMedia *media);
 
123
static void purple_media_candidate_pair_established_cb(
 
124
                PurpleMediaBackend *backend,
 
125
                const gchar *sess_id, const gchar *name,
 
126
                PurpleMediaCandidate *local_candidate,
 
127
                PurpleMediaCandidate *remote_candidate,
 
128
                PurpleMedia *media);
 
129
static void purple_media_codecs_changed_cb(PurpleMediaBackend *backend,
 
130
                const gchar *sess_id, PurpleMedia *media);
 
131
 
 
132
static GObjectClass *parent_class = NULL;
 
133
 
 
134
 
 
135
 
 
136
enum {
 
137
        S_ERROR,
 
138
        CANDIDATES_PREPARED,
 
139
        CODECS_CHANGED,
 
140
        LEVEL,
 
141
        NEW_CANDIDATE,
 
142
        STATE_CHANGED,
 
143
        STREAM_INFO,
 
144
        LAST_SIGNAL
 
145
};
 
146
static guint purple_media_signals[LAST_SIGNAL] = {0};
 
147
 
 
148
enum {
 
149
        PROP_0,
 
150
        PROP_MANAGER,
 
151
        PROP_BACKEND,
 
152
        PROP_ACCOUNT,
 
153
        PROP_CONFERENCE_TYPE,
 
154
        PROP_INITIATOR,
 
155
        PROP_PRPL_DATA,
 
156
};
 
157
#endif
 
158
 
 
159
 
 
160
GType
 
161
purple_media_get_type()
 
162
{
 
163
#ifdef USE_VV
 
164
        static GType type = 0;
 
165
 
 
166
        if (type == 0) {
 
167
                static const GTypeInfo info = {
 
168
                        sizeof(PurpleMediaClass),
 
169
                        NULL,
 
170
                        NULL,
 
171
                        (GClassInitFunc) purple_media_class_init,
 
172
                        NULL,
 
173
                        NULL,
 
174
                        sizeof(PurpleMedia),
 
175
                        0,
 
176
                        (GInstanceInitFunc) purple_media_init,
 
177
                        NULL
 
178
                };
 
179
                type = g_type_register_static(G_TYPE_OBJECT, "PurpleMedia", &info, 0);
 
180
        }
 
181
        return type;
 
182
#else
 
183
        return G_TYPE_NONE;
 
184
#endif
 
185
}
 
186
 
 
187
#ifdef USE_VV
 
188
static void
 
189
purple_media_class_init (PurpleMediaClass *klass)
 
190
{
 
191
        GObjectClass *gobject_class = (GObjectClass*)klass;
 
192
        parent_class = g_type_class_peek_parent(klass);
 
193
 
 
194
        gobject_class->dispose = purple_media_dispose;
 
195
        gobject_class->finalize = purple_media_finalize;
 
196
        gobject_class->set_property = purple_media_set_property;
 
197
        gobject_class->get_property = purple_media_get_property;
 
198
 
 
199
        g_object_class_install_property(gobject_class, PROP_MANAGER,
 
200
                        g_param_spec_object("manager",
 
201
                        "Purple Media Manager",
 
202
                        "The media manager that contains this media session.",
 
203
                        PURPLE_TYPE_MEDIA_MANAGER,
 
204
                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
205
 
 
206
        /*
 
207
         * This one should be PURPLE_TYPE_MEDIA_BACKEND, but it doesn't
 
208
         * like interfaces because they "aren't GObjects"
 
209
         */
 
210
        g_object_class_install_property(gobject_class, PROP_BACKEND,
 
211
                        g_param_spec_object("backend",
 
212
                        "Purple Media Backend",
 
213
                        "The backend object this media object uses.",
 
214
                        G_TYPE_OBJECT,
 
215
                        G_PARAM_READABLE));
 
216
 
 
217
        g_object_class_install_property(gobject_class, PROP_ACCOUNT,
 
218
                        g_param_spec_pointer("account",
 
219
                        "PurpleAccount",
 
220
                        "The account this media session is on.",
 
221
                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
222
 
 
223
        g_object_class_install_property(gobject_class, PROP_CONFERENCE_TYPE,
 
224
                        g_param_spec_string("conference-type",
 
225
                        "Conference Type",
 
226
                        "The type of conference that this media object "
 
227
                        "has been created to provide.",
 
228
                        NULL,
 
229
                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
230
 
 
231
        g_object_class_install_property(gobject_class, PROP_INITIATOR,
 
232
                        g_param_spec_boolean("initiator",
 
233
                        "initiator",
 
234
                        "If the local user initiated the conference.",
 
235
                        FALSE,
 
236
                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
237
 
 
238
        g_object_class_install_property(gobject_class, PROP_PRPL_DATA,
 
239
                        g_param_spec_pointer("prpl-data",
 
240
                        "gpointer",
 
241
                        "Data the prpl plugin set on the media session.",
 
242
                        G_PARAM_READWRITE));
 
243
 
 
244
        purple_media_signals[S_ERROR] = g_signal_new("error", G_TYPE_FROM_CLASS(klass),
 
245
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
246
                                         g_cclosure_marshal_VOID__STRING,
 
247
                                         G_TYPE_NONE, 1, G_TYPE_STRING);
 
248
        purple_media_signals[CANDIDATES_PREPARED] = g_signal_new("candidates-prepared", G_TYPE_FROM_CLASS(klass),
 
249
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
250
                                         purple_smarshal_VOID__STRING_STRING,
 
251
                                         G_TYPE_NONE, 2, G_TYPE_STRING,
 
252
                                         G_TYPE_STRING);
 
253
        purple_media_signals[CODECS_CHANGED] = g_signal_new("codecs-changed", G_TYPE_FROM_CLASS(klass),
 
254
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
255
                                         g_cclosure_marshal_VOID__STRING,
 
256
                                         G_TYPE_NONE, 1, G_TYPE_STRING);
 
257
        purple_media_signals[LEVEL] = g_signal_new("level", G_TYPE_FROM_CLASS(klass),
 
258
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
259
                                         purple_smarshal_VOID__STRING_STRING_DOUBLE,
 
260
                                         G_TYPE_NONE, 3, G_TYPE_STRING,
 
261
                                         G_TYPE_STRING, G_TYPE_DOUBLE);
 
262
        purple_media_signals[NEW_CANDIDATE] = g_signal_new("new-candidate", G_TYPE_FROM_CLASS(klass),
 
263
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
264
                                         purple_smarshal_VOID__POINTER_POINTER_OBJECT,
 
265
                                         G_TYPE_NONE, 3, G_TYPE_POINTER,
 
266
                                         G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE);
 
267
        purple_media_signals[STATE_CHANGED] = g_signal_new("state-changed", G_TYPE_FROM_CLASS(klass),
 
268
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
269
                                         purple_smarshal_VOID__ENUM_STRING_STRING,
 
270
                                         G_TYPE_NONE, 3, PURPLE_MEDIA_TYPE_STATE,
 
271
                                         G_TYPE_STRING, G_TYPE_STRING);
 
272
        purple_media_signals[STREAM_INFO] = g_signal_new("stream-info", G_TYPE_FROM_CLASS(klass),
 
273
                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
274
                                         purple_smarshal_VOID__ENUM_STRING_STRING_BOOLEAN,
 
275
                                         G_TYPE_NONE, 4, PURPLE_MEDIA_TYPE_INFO_TYPE,
 
276
                                         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
277
        g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
 
278
}
 
279
 
 
280
 
 
281
static void
 
282
purple_media_init (PurpleMedia *media)
 
283
{
 
284
        media->priv = PURPLE_MEDIA_GET_PRIVATE(media);
 
285
        memset(media->priv, 0, sizeof(*media->priv));
 
286
}
 
287
 
 
288
static void
 
289
purple_media_stream_free(PurpleMediaStream *stream)
 
290
{
 
291
        if (stream == NULL)
 
292
                return;
 
293
 
 
294
        g_free(stream->participant);
 
295
 
 
296
        if (stream->local_candidates)
 
297
                purple_media_candidate_list_free(stream->local_candidates);
 
298
        if (stream->remote_candidates)
 
299
                purple_media_candidate_list_free(stream->remote_candidates);
 
300
 
 
301
        if (stream->active_local_candidates)
 
302
                purple_media_candidate_list_free(
 
303
                                stream->active_local_candidates);
 
304
        if (stream->active_remote_candidates)
 
305
                purple_media_candidate_list_free(
 
306
                                stream->active_remote_candidates);
 
307
 
 
308
        g_free(stream);
 
309
}
 
310
 
 
311
static void
 
312
purple_media_session_free(PurpleMediaSession *session)
 
313
{
 
314
        if (session == NULL)
 
315
                return;
 
316
 
 
317
        g_free(session->id);
 
318
        g_free(session);
 
319
}
 
320
 
 
321
static void
 
322
purple_media_dispose(GObject *media)
 
323
{
 
324
        PurpleMediaPrivate *priv = PURPLE_MEDIA_GET_PRIVATE(media);
 
325
 
 
326
        purple_debug_info("media","purple_media_dispose\n");
 
327
 
 
328
        purple_media_manager_remove_media(priv->manager, PURPLE_MEDIA(media));
 
329
 
 
330
        if (priv->backend) {
 
331
                g_object_unref(priv->backend);
 
332
                priv->backend = NULL;
 
333
        }
 
334
 
 
335
        if (priv->manager) {
 
336
                g_object_unref(priv->manager);
 
337
                priv->manager = NULL;
 
338
        }
 
339
 
 
340
        G_OBJECT_CLASS(parent_class)->dispose(media);
 
341
}
 
342
 
 
343
static void
 
344
purple_media_finalize(GObject *media)
 
345
{
 
346
        PurpleMediaPrivate *priv = PURPLE_MEDIA_GET_PRIVATE(media);
 
347
        purple_debug_info("media","purple_media_finalize\n");
 
348
 
 
349
        for (; priv->streams; priv->streams = g_list_delete_link(priv->streams, priv->streams))
 
350
                purple_media_stream_free(priv->streams->data);
 
351
 
 
352
        for (; priv->participants; priv->participants = g_list_delete_link(
 
353
                        priv->participants, priv->participants))
 
354
                g_free(priv->participants->data);
 
355
 
 
356
        if (priv->sessions) {
 
357
                GList *sessions = g_hash_table_get_values(priv->sessions);
 
358
                for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
 
359
                        purple_media_session_free(sessions->data);
 
360
                }
 
361
                g_hash_table_destroy(priv->sessions);
 
362
        }
 
363
 
 
364
        G_OBJECT_CLASS(parent_class)->finalize(media);
 
365
}
 
366
 
 
367
static void
 
368
purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 
369
{
 
370
        PurpleMedia *media;
 
371
        g_return_if_fail(PURPLE_IS_MEDIA(object));
 
372
 
 
373
        media = PURPLE_MEDIA(object);
 
374
 
 
375
        switch (prop_id) {
 
376
                case PROP_MANAGER:
 
377
                        media->priv->manager = g_value_dup_object(value);
 
378
                        break;
 
379
                case PROP_ACCOUNT:
 
380
                        media->priv->account = g_value_get_pointer(value);
 
381
                        break;
 
382
                case PROP_CONFERENCE_TYPE:
 
383
                        media->priv->conference_type =
 
384
                                        g_value_dup_string(value);
 
385
                        media->priv->backend = g_object_new(
 
386
                                        purple_media_manager_get_backend_type(
 
387
                                        purple_media_manager_get()),
 
388
                                        "conference-type",
 
389
                                        media->priv->conference_type,
 
390
                                        "media", media,
 
391
                                        NULL);
 
392
                        g_signal_connect(media->priv->backend,
 
393
                                        "active-candidate-pair",
 
394
                                        G_CALLBACK(
 
395
                                        purple_media_candidate_pair_established_cb),
 
396
                                        media);
 
397
                        g_signal_connect(media->priv->backend,
 
398
                                        "candidates-prepared",
 
399
                                        G_CALLBACK(
 
400
                                        purple_media_candidates_prepared_cb),
 
401
                                        media);
 
402
                        g_signal_connect(media->priv->backend,
 
403
                                        "codecs-changed",
 
404
                                        G_CALLBACK(
 
405
                                        purple_media_codecs_changed_cb),
 
406
                                        media);
 
407
                        g_signal_connect(media->priv->backend,
 
408
                                        "new-candidate",
 
409
                                        G_CALLBACK(
 
410
                                        purple_media_new_local_candidate_cb),
 
411
                                        media);
 
412
                        break;
 
413
                case PROP_INITIATOR:
 
414
                        media->priv->initiator = g_value_get_boolean(value);
 
415
                        break;
 
416
                case PROP_PRPL_DATA:
 
417
                        media->priv->prpl_data = g_value_get_pointer(value);
 
418
                        break;
 
419
                default:
 
420
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
421
                        break;
 
422
        }
 
423
}
 
424
 
 
425
static void
 
426
purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 
427
{
 
428
        PurpleMedia *media;
 
429
        g_return_if_fail(PURPLE_IS_MEDIA(object));
 
430
 
 
431
        media = PURPLE_MEDIA(object);
 
432
 
 
433
        switch (prop_id) {
 
434
                case PROP_MANAGER:
 
435
                        g_value_set_object(value, media->priv->manager);
 
436
                        break;
 
437
                case PROP_BACKEND:
 
438
                        g_value_set_object(value, media->priv->backend);
 
439
                        break;
 
440
                case PROP_ACCOUNT:
 
441
                        g_value_set_pointer(value, media->priv->account);
 
442
                        break;
 
443
                case PROP_CONFERENCE_TYPE:
 
444
                        g_value_set_string(value,
 
445
                                        media->priv->conference_type);
 
446
                        break;
 
447
                case PROP_INITIATOR:
 
448
                        g_value_set_boolean(value, media->priv->initiator);
 
449
                        break;
 
450
                case PROP_PRPL_DATA:
 
451
                        g_value_set_pointer(value, media->priv->prpl_data);
 
452
                        break;
 
453
                default:
 
454
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
455
                        break;
 
456
        }
 
457
 
 
458
}
 
459
 
 
460
static PurpleMediaSession*
 
461
purple_media_get_session(PurpleMedia *media, const gchar *sess_id)
 
462
{
 
463
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
464
        return (PurpleMediaSession*) (media->priv->sessions) ?
 
465
                        g_hash_table_lookup(media->priv->sessions, sess_id) : NULL;
 
466
}
 
467
 
 
468
static PurpleMediaStream*
 
469
purple_media_get_stream(PurpleMedia *media, const gchar *session, const gchar *participant)
 
470
{
 
471
        GList *streams;
 
472
 
 
473
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
474
 
 
475
        streams = media->priv->streams;
 
476
 
 
477
        for (; streams; streams = g_list_next(streams)) {
 
478
                PurpleMediaStream *stream = streams->data;
 
479
                if (!strcmp(stream->session->id, session) &&
 
480
                                !strcmp(stream->participant, participant))
 
481
                        return stream;
 
482
        }
 
483
 
 
484
        return NULL;
 
485
}
 
486
 
 
487
static GList *
 
488
purple_media_get_streams(PurpleMedia *media, const gchar *session,
 
489
                const gchar *participant)
 
490
{
 
491
        GList *streams;
 
492
        GList *ret = NULL;
 
493
 
 
494
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
495
 
 
496
        streams = media->priv->streams;
 
497
 
 
498
        for (; streams; streams = g_list_next(streams)) {
 
499
                PurpleMediaStream *stream = streams->data;
 
500
                if ((session == NULL ||
 
501
                                !strcmp(stream->session->id, session)) &&
 
502
                                (participant == NULL ||
 
503
                                !strcmp(stream->participant, participant)))
 
504
                        ret = g_list_append(ret, stream);
 
505
        }
 
506
 
 
507
        return ret;
 
508
}
 
509
 
 
510
static void
 
511
purple_media_add_session(PurpleMedia *media, PurpleMediaSession *session)
 
512
{
 
513
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
514
        g_return_if_fail(session != NULL);
 
515
 
 
516
        if (!media->priv->sessions) {
 
517
                purple_debug_info("media", "Creating hash table for sessions\n");
 
518
                media->priv->sessions = g_hash_table_new_full(g_str_hash, g_str_equal,
 
519
                                                              g_free, NULL);
 
520
        }
 
521
        g_hash_table_insert(media->priv->sessions, g_strdup(session->id), session);
 
522
}
 
523
 
 
524
#if 0
 
525
static gboolean
 
526
purple_media_remove_session(PurpleMedia *media, PurpleMediaSession *session)
 
527
{
 
528
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
529
        return g_hash_table_remove(media->priv->sessions, session->id);
 
530
}
 
531
#endif
 
532
 
 
533
static PurpleMediaStream *
 
534
purple_media_insert_stream(PurpleMediaSession *session,
 
535
                const gchar *name, gboolean initiator)
 
536
{
 
537
        PurpleMediaStream *media_stream;
 
538
 
 
539
        g_return_val_if_fail(session != NULL, NULL);
 
540
 
 
541
        media_stream = g_new0(PurpleMediaStream, 1);
 
542
        media_stream->participant = g_strdup(name);
 
543
        media_stream->session = session;
 
544
        media_stream->initiator = initiator;
 
545
 
 
546
        session->media->priv->streams =
 
547
                        g_list_append(session->media->priv->streams, media_stream);
 
548
 
 
549
        return media_stream;
 
550
}
 
551
 
 
552
static void
 
553
purple_media_insert_local_candidate(PurpleMediaSession *session, const gchar *name,
 
554
                                     PurpleMediaCandidate *candidate)
 
555
{
 
556
        PurpleMediaStream *stream;
 
557
 
 
558
        g_return_if_fail(session != NULL);
 
559
 
 
560
        stream = purple_media_get_stream(session->media, session->id, name);
 
561
        stream->local_candidates = g_list_append(stream->local_candidates, candidate);
 
562
}
 
563
#endif
 
564
 
 
565
GList *
 
566
purple_media_get_session_ids(PurpleMedia *media)
 
567
{
 
568
#ifdef USE_VV
 
569
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
570
        return media->priv->sessions != NULL ?
 
571
                        g_hash_table_get_keys(media->priv->sessions) : NULL;
 
572
#else
 
573
        return NULL;
 
574
#endif
 
575
}
 
576
 
 
577
#ifdef USE_GSTREAMER
 
578
GstElement *
 
579
purple_media_get_src(PurpleMedia *media, const gchar *sess_id)
 
580
{
 
581
#ifdef USE_VV
 
582
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
583
 
 
584
        if (PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend))
 
585
                return purple_media_backend_fs2_get_src(
 
586
                                PURPLE_MEDIA_BACKEND_FS2(
 
587
                                media->priv->backend), sess_id);
 
588
 
 
589
        g_return_val_if_reached(NULL);
 
590
#else
 
591
        return NULL;
 
592
#endif
 
593
}
 
594
#endif /* USE_GSTREAMER */
 
595
 
 
596
PurpleAccount *
 
597
purple_media_get_account(PurpleMedia *media)
 
598
{
 
599
#ifdef USE_VV
 
600
        PurpleAccount *account;
 
601
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
602
        g_object_get(G_OBJECT(media), "account", &account, NULL);
 
603
        return account;
 
604
#else
 
605
        return NULL;
 
606
#endif
 
607
}
 
608
 
 
609
gpointer
 
610
purple_media_get_prpl_data(PurpleMedia *media)
 
611
{
 
612
#ifdef USE_VV
 
613
        gpointer prpl_data;
 
614
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
615
        g_object_get(G_OBJECT(media), "prpl-data", &prpl_data, NULL);
 
616
        return prpl_data;
 
617
#else
 
618
        return NULL;
 
619
#endif
 
620
}
 
621
 
 
622
void
 
623
purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data)
 
624
{
 
625
#ifdef USE_VV
 
626
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
627
        g_object_set(G_OBJECT(media), "prpl-data", prpl_data, NULL);
 
628
#endif
 
629
}
 
630
 
 
631
void
 
632
purple_media_error(PurpleMedia *media, const gchar *error, ...)
 
633
{
 
634
#ifdef USE_VV
 
635
        va_list args;
 
636
        gchar *message;
 
637
 
 
638
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
639
 
 
640
        va_start(args, error);
 
641
        message = g_strdup_vprintf(error, args);
 
642
        va_end(args);
 
643
 
 
644
        purple_debug_error("media", "%s\n", message);
 
645
        g_signal_emit(media, purple_media_signals[S_ERROR], 0, message);
 
646
 
 
647
        g_free(message);
 
648
#endif
 
649
}
 
650
 
 
651
void
 
652
purple_media_end(PurpleMedia *media,
 
653
                const gchar *session_id, const gchar *participant)
 
654
{
 
655
#ifdef USE_VV
 
656
        GList *iter, *sessions = NULL, *participants = NULL;
 
657
 
 
658
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
659
 
 
660
        iter = purple_media_get_streams(media, session_id, participant);
 
661
 
 
662
        /* Free matching streams */
 
663
        for (; iter; iter = g_list_delete_link(iter, iter)) {
 
664
                PurpleMediaStream *stream = iter->data;
 
665
 
 
666
                g_signal_emit(media, purple_media_signals[STATE_CHANGED],
 
667
                                0, PURPLE_MEDIA_STATE_END,
 
668
                                stream->session->id, stream->participant);
 
669
 
 
670
                media->priv->streams =
 
671
                                g_list_remove(media->priv->streams, stream);
 
672
 
 
673
                if (g_list_find(sessions, stream->session) == NULL)
 
674
                        sessions = g_list_prepend(sessions, stream->session);
 
675
 
 
676
                if (g_list_find_custom(participants, stream->participant,
 
677
                                (GCompareFunc)strcmp) == NULL)
 
678
                        participants = g_list_prepend(participants,
 
679
                                        g_strdup(stream->participant));
 
680
 
 
681
                purple_media_stream_free(stream);
 
682
        }
 
683
 
 
684
        iter = media->priv->streams;
 
685
 
 
686
        /* Reduce to list of sessions to remove */
 
687
        for (; iter; iter = g_list_next(iter)) {
 
688
                PurpleMediaStream *stream = iter->data;
 
689
 
 
690
                sessions = g_list_remove(sessions, stream->session);
 
691
        }
 
692
 
 
693
        /* Free sessions with no streams left */
 
694
        for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
 
695
                PurpleMediaSession *session = sessions->data;
 
696
 
 
697
                g_signal_emit(media, purple_media_signals[STATE_CHANGED],
 
698
                                0, PURPLE_MEDIA_STATE_END,
 
699
                                session->id, NULL);
 
700
 
 
701
                g_hash_table_remove(media->priv->sessions, session->id);
 
702
                purple_media_session_free(session);
 
703
        }
 
704
 
 
705
        iter = media->priv->streams;
 
706
 
 
707
        /* Reduce to list of participants to remove */
 
708
        for (; iter; iter = g_list_next(iter)) {
 
709
                PurpleMediaStream *stream = iter->data;
 
710
                GList *tmp;
 
711
 
 
712
                tmp = g_list_find_custom(participants,
 
713
                                stream->participant, (GCompareFunc)strcmp);
 
714
 
 
715
                if (tmp != NULL) {
 
716
                        g_free(tmp->data);
 
717
                        participants = g_list_delete_link(participants, tmp);
 
718
                }
 
719
        }
 
720
 
 
721
        /* Remove participants with no streams left (just emit the signal) */
 
722
        for (; participants; participants =
 
723
                        g_list_delete_link(participants, participants)) {
 
724
                gchar *participant = participants->data;
 
725
                GList *link = g_list_find_custom(media->priv->participants,
 
726
                                participant, (GCompareFunc)strcmp);
 
727
 
 
728
                g_signal_emit(media, purple_media_signals[STATE_CHANGED],
 
729
                                0, PURPLE_MEDIA_STATE_END,
 
730
                                NULL, participant);
 
731
 
 
732
                if (link != NULL) {
 
733
                        g_free(link->data);
 
734
                        media->priv->participants = g_list_delete_link(
 
735
                                        media->priv->participants, link);
 
736
                }
 
737
 
 
738
                g_free(participant);
 
739
        }
 
740
 
 
741
        /* Free the conference if no sessions left */
 
742
        if (media->priv->sessions != NULL &&
 
743
                        g_hash_table_size(media->priv->sessions) == 0) {
 
744
                g_signal_emit(media, purple_media_signals[STATE_CHANGED],
 
745
                                0, PURPLE_MEDIA_STATE_END,
 
746
                                NULL, NULL);
 
747
                g_object_unref(media);
 
748
                return;
 
749
        }
 
750
#endif
 
751
}
 
752
 
 
753
void
 
754
purple_media_stream_info(PurpleMedia *media, PurpleMediaInfoType type,
 
755
                const gchar *session_id, const gchar *participant,
 
756
                gboolean local)
 
757
{
 
758
#ifdef USE_VV
 
759
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
760
 
 
761
        if (type == PURPLE_MEDIA_INFO_ACCEPT) {
 
762
                GList *streams, *sessions = NULL, *participants = NULL;
 
763
 
 
764
                g_return_if_fail(PURPLE_IS_MEDIA(media));
 
765
 
 
766
                streams = purple_media_get_streams(media,
 
767
                                session_id, participant);
 
768
 
 
769
                /* Emit stream acceptance */
 
770
                for (; streams; streams =
 
771
                                g_list_delete_link(streams, streams)) {
 
772
                        PurpleMediaStream *stream = streams->data;
 
773
 
 
774
                        stream->accepted = TRUE;
 
775
 
 
776
                        g_signal_emit(media,
 
777
                                        purple_media_signals[STREAM_INFO],
 
778
                                        0, type, stream->session->id,
 
779
                                        stream->participant, local);
 
780
 
 
781
                        if (g_list_find(sessions, stream->session) == NULL)
 
782
                                sessions = g_list_prepend(sessions,
 
783
                                                stream->session);
 
784
 
 
785
                        if (g_list_find_custom(participants,
 
786
                                        stream->participant,
 
787
                                        (GCompareFunc)strcmp) == NULL)
 
788
                                participants = g_list_prepend(participants,
 
789
                                                g_strdup(stream->participant));
 
790
                }
 
791
 
 
792
                /* Emit session acceptance */
 
793
                for (; sessions; sessions =
 
794
                                g_list_delete_link(sessions, sessions)) {
 
795
                        PurpleMediaSession *session = sessions->data;
 
796
 
 
797
                        if (purple_media_accepted(media, session->id, NULL))
 
798
                                g_signal_emit(media, purple_media_signals[
 
799
                                                STREAM_INFO], 0,
 
800
                                                PURPLE_MEDIA_INFO_ACCEPT,
 
801
                                                session->id, NULL, local);
 
802
                }
 
803
 
 
804
                /* Emit participant acceptance */
 
805
                for (; participants; participants = g_list_delete_link(
 
806
                                participants, participants)) {
 
807
                        gchar *participant = participants->data;
 
808
 
 
809
                        if (purple_media_accepted(media, NULL, participant))
 
810
                                g_signal_emit(media, purple_media_signals[
 
811
                                                STREAM_INFO], 0,
 
812
                                                PURPLE_MEDIA_INFO_ACCEPT,
 
813
                                                NULL, participant, local);
 
814
 
 
815
                        g_free(participant);
 
816
                }
 
817
 
 
818
                /* Emit conference acceptance */
 
819
                if (purple_media_accepted(media, NULL, NULL))
 
820
                        g_signal_emit(media,
 
821
                                        purple_media_signals[STREAM_INFO],
 
822
                                        0, PURPLE_MEDIA_INFO_ACCEPT,
 
823
                                        NULL, NULL, local);
 
824
 
 
825
                return;
 
826
        } else if (type == PURPLE_MEDIA_INFO_HANGUP ||
 
827
                        type == PURPLE_MEDIA_INFO_REJECT) {
 
828
                GList *streams;
 
829
 
 
830
                g_return_if_fail(PURPLE_IS_MEDIA(media));
 
831
 
 
832
                streams = purple_media_get_streams(media,
 
833
                                session_id, participant);
 
834
 
 
835
                /* Emit for stream */
 
836
                for (; streams; streams =
 
837
                                g_list_delete_link(streams, streams)) {
 
838
                        PurpleMediaStream *stream = streams->data;
 
839
 
 
840
                        g_signal_emit(media,
 
841
                                        purple_media_signals[STREAM_INFO],
 
842
                                        0, type, stream->session->id,
 
843
                                        stream->participant, local);
 
844
                }
 
845
 
 
846
                if (session_id != NULL && participant != NULL) {
 
847
                        /* Everything that needs to be emitted has been */
 
848
                } else if (session_id == NULL && participant == NULL) {
 
849
                        /* Emit for everything in the conference */
 
850
                        GList *sessions = NULL;
 
851
                        GList *participants = media->priv->participants;
 
852
 
 
853
                        if (media->priv->sessions != NULL)
 
854
                                sessions = g_hash_table_get_values(
 
855
                                        media->priv->sessions);
 
856
 
 
857
                        /* Emit for sessions */
 
858
                        for (; sessions; sessions = g_list_delete_link(
 
859
                                        sessions, sessions)) {
 
860
                                PurpleMediaSession *session = sessions->data;
 
861
 
 
862
                                g_signal_emit(media, purple_media_signals[
 
863
                                                STREAM_INFO], 0, type,
 
864
                                                session->id, NULL, local);
 
865
                        }
 
866
 
 
867
                        /* Emit for participants */
 
868
                        for (; participants; participants =
 
869
                                        g_list_next(participants)) {
 
870
                                gchar *participant = participants->data;
 
871
 
 
872
                                g_signal_emit(media, purple_media_signals[
 
873
                                                STREAM_INFO], 0, type,
 
874
                                                NULL, participant, local);
 
875
                        }
 
876
 
 
877
                        /* Emit for conference */
 
878
                        g_signal_emit(media,
 
879
                                        purple_media_signals[STREAM_INFO],
 
880
                                        0, type, NULL, NULL, local);
 
881
                } else if (session_id != NULL) {
 
882
                        /* Emit just the specific session */
 
883
                        PurpleMediaSession *session =
 
884
                                        purple_media_get_session(
 
885
                                        media, session_id);
 
886
 
 
887
                        if (session == NULL) {
 
888
                                purple_debug_warning("media",
 
889
                                                "Couldn't find session"
 
890
                                                " to hangup/reject.\n");
 
891
                        } else {
 
892
                                g_signal_emit(media, purple_media_signals[
 
893
                                                STREAM_INFO], 0, type,
 
894
                                                session->id, NULL, local);
 
895
                        }
 
896
                } else if (participant != NULL) {
 
897
                        /* Emit just the specific participant */
 
898
                        if (!g_list_find_custom(media->priv->participants,
 
899
                                        participant, (GCompareFunc)strcmp)) {
 
900
                                purple_debug_warning("media",
 
901
                                                "Couldn't find participant"
 
902
                                                " to hangup/reject.\n");
 
903
                        } else {
 
904
                                g_signal_emit(media, purple_media_signals[
 
905
                                                STREAM_INFO], 0, type, NULL,
 
906
                                                participant, local);
 
907
                        }
 
908
                }
 
909
 
 
910
                purple_media_end(media, session_id, participant);
 
911
                return;
 
912
        }
 
913
 
 
914
        g_signal_emit(media, purple_media_signals[STREAM_INFO],
 
915
                        0, type, session_id, participant, local);
 
916
#endif
 
917
}
 
918
 
 
919
void
 
920
purple_media_set_params(PurpleMedia *media,
 
921
                guint num_params, GParameter *params)
 
922
{
 
923
#ifdef USE_VV
 
924
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
925
 
 
926
        purple_media_backend_set_params(media->priv->backend, num_params, params);
 
927
#endif
 
928
}
 
929
 
 
930
const gchar **
 
931
purple_media_get_available_params(PurpleMedia *media)
 
932
{
 
933
        static const gchar *NULL_ARRAY[] = { NULL };
 
934
#ifdef USE_VV
 
935
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL_ARRAY);
 
936
 
 
937
        return purple_media_backend_get_available_params(media->priv->backend);
 
938
#else
 
939
        return NULL_ARRAY;
 
940
#endif
 
941
}
 
942
 
 
943
gboolean
 
944
purple_media_param_is_supported(PurpleMedia *media, const gchar *param)
 
945
{
 
946
#ifdef USE_VV
 
947
        const gchar **params;
 
948
 
 
949
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
950
        g_return_val_if_fail(param != NULL, FALSE);
 
951
 
 
952
        params = purple_media_backend_get_available_params(media->priv->backend);
 
953
        for (; *params != NULL; ++params)
 
954
                if (!strcmp(*params, param))
 
955
                        return TRUE;
 
956
#endif
 
957
        return FALSE;
 
958
}
 
959
 
 
960
#ifdef USE_VV
 
961
static void
 
962
purple_media_new_local_candidate_cb(PurpleMediaBackend *backend,
 
963
                const gchar *sess_id, const gchar *participant,
 
964
                PurpleMediaCandidate *candidate, PurpleMedia *media)
 
965
{
 
966
        PurpleMediaSession *session =
 
967
                        purple_media_get_session(media, sess_id);
 
968
 
 
969
        purple_media_insert_local_candidate(session, participant,
 
970
                        purple_media_candidate_copy(candidate));
 
971
 
 
972
        g_signal_emit(session->media, purple_media_signals[NEW_CANDIDATE],
 
973
                      0, session->id, participant, candidate);
 
974
}
 
975
 
 
976
static void
 
977
purple_media_candidates_prepared_cb(PurpleMediaBackend *backend,
 
978
                const gchar *sess_id, const gchar *name, PurpleMedia *media)
 
979
{
 
980
        PurpleMediaStream *stream_data;
 
981
 
 
982
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
983
 
 
984
        stream_data = purple_media_get_stream(media, sess_id, name);
 
985
        stream_data->candidates_prepared = TRUE;
 
986
 
 
987
        g_signal_emit(media, purple_media_signals[CANDIDATES_PREPARED],
 
988
                        0, sess_id, name);
 
989
}
 
990
 
 
991
/* callback called when a pair of transport candidates (local and remote)
 
992
 * has been established */
 
993
static void
 
994
purple_media_candidate_pair_established_cb(PurpleMediaBackend *backend,
 
995
                const gchar *sess_id, const gchar *name,
 
996
                PurpleMediaCandidate *local_candidate,
 
997
                PurpleMediaCandidate *remote_candidate,
 
998
                PurpleMedia *media)
 
999
{
 
1000
        PurpleMediaStream *stream;
 
1001
        GList *iter;
 
1002
        guint id;
 
1003
 
 
1004
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
1005
 
 
1006
        stream = purple_media_get_stream(media, sess_id, name);
 
1007
        id = purple_media_candidate_get_component_id(local_candidate);
 
1008
 
 
1009
        iter = stream->active_local_candidates;
 
1010
        for(; iter; iter = g_list_next(iter)) {
 
1011
                PurpleMediaCandidate *c = iter->data;
 
1012
                if (id == purple_media_candidate_get_component_id(c)) {
 
1013
                        g_object_unref(c);
 
1014
                        stream->active_local_candidates =
 
1015
                                        g_list_delete_link(iter, iter);
 
1016
                        stream->active_local_candidates = g_list_prepend(
 
1017
                                        stream->active_local_candidates,
 
1018
                                        purple_media_candidate_copy(
 
1019
                                        local_candidate));
 
1020
                        break;
 
1021
                }
 
1022
        }
 
1023
        if (iter == NULL)
 
1024
                stream->active_local_candidates = g_list_prepend(
 
1025
                                stream->active_local_candidates,
 
1026
                                purple_media_candidate_copy(
 
1027
                                local_candidate));
 
1028
 
 
1029
        id = purple_media_candidate_get_component_id(local_candidate);
 
1030
 
 
1031
        iter = stream->active_remote_candidates;
 
1032
        for(; iter; iter = g_list_next(iter)) {
 
1033
                PurpleMediaCandidate *c = iter->data;
 
1034
                if (id == purple_media_candidate_get_component_id(c)) {
 
1035
                        g_object_unref(c);
 
1036
                        stream->active_remote_candidates =
 
1037
                                        g_list_delete_link(iter, iter);
 
1038
                        stream->active_remote_candidates = g_list_prepend(
 
1039
                                        stream->active_remote_candidates,
 
1040
                                        purple_media_candidate_copy(
 
1041
                                        remote_candidate));
 
1042
                        break;
 
1043
                }
 
1044
        }
 
1045
        if (iter == NULL)
 
1046
                stream->active_remote_candidates = g_list_prepend(
 
1047
                                stream->active_remote_candidates,
 
1048
                                purple_media_candidate_copy(
 
1049
                                remote_candidate));
 
1050
 
 
1051
        purple_debug_info("media", "candidate pair established\n");
 
1052
}
 
1053
 
 
1054
static void
 
1055
purple_media_codecs_changed_cb(PurpleMediaBackend *backend,
 
1056
                const gchar *sess_id, PurpleMedia *media)
 
1057
{
 
1058
        g_signal_emit(media, purple_media_signals[CODECS_CHANGED], 0, sess_id);
 
1059
}
 
1060
#endif  /* USE_VV */
 
1061
 
 
1062
gboolean
 
1063
purple_media_add_stream(PurpleMedia *media, const gchar *sess_id,
 
1064
                const gchar *who, PurpleMediaSessionType type,
 
1065
                gboolean initiator, const gchar *transmitter,
 
1066
                guint num_params, GParameter *params)
 
1067
{
 
1068
#ifdef USE_VV
 
1069
        PurpleMediaSession *session;
 
1070
        PurpleMediaStream *stream = NULL;
 
1071
 
 
1072
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1073
 
 
1074
        if (!purple_media_backend_add_stream(media->priv->backend,
 
1075
                        sess_id, who, type, initiator, transmitter,
 
1076
                        num_params, params)) {
 
1077
                purple_debug_error("media", "Error adding stream.\n");
 
1078
                return FALSE;
 
1079
        }
 
1080
 
 
1081
        session = purple_media_get_session(media, sess_id);
 
1082
 
 
1083
        if (!session) {
 
1084
                session = g_new0(PurpleMediaSession, 1);
 
1085
                session->id = g_strdup(sess_id);
 
1086
                session->media = media;
 
1087
                session->type = type;
 
1088
                session->initiator = initiator;
 
1089
 
 
1090
                purple_media_add_session(media, session);
 
1091
                g_signal_emit(media, purple_media_signals[STATE_CHANGED],
 
1092
                                0, PURPLE_MEDIA_STATE_NEW,
 
1093
                                session->id, NULL);
 
1094
        }
 
1095
 
 
1096
        if (!g_list_find_custom(media->priv->participants,
 
1097
                        who, (GCompareFunc)strcmp)) {
 
1098
                media->priv->participants = g_list_prepend(
 
1099
                                media->priv->participants, g_strdup(who));
 
1100
 
 
1101
                g_signal_emit_by_name(media, "state-changed",
 
1102
                                PURPLE_MEDIA_STATE_NEW, NULL, who);
 
1103
        }
 
1104
 
 
1105
        if (purple_media_get_stream(media, sess_id, who) == NULL) {
 
1106
                stream = purple_media_insert_stream(session, who, initiator);
 
1107
 
 
1108
                g_signal_emit(media, purple_media_signals[STATE_CHANGED],
 
1109
                                0, PURPLE_MEDIA_STATE_NEW,
 
1110
                                session->id, who);
 
1111
        }
 
1112
 
 
1113
        return TRUE;
 
1114
#else
 
1115
        return FALSE;
 
1116
#endif  /* USE_VV */
 
1117
}
 
1118
 
 
1119
PurpleMediaManager *
 
1120
purple_media_get_manager(PurpleMedia *media)
 
1121
{
 
1122
        PurpleMediaManager *ret;
 
1123
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
1124
        g_object_get(media, "manager", &ret, NULL);
 
1125
        return ret;
 
1126
}
 
1127
 
 
1128
PurpleMediaSessionType
 
1129
purple_media_get_session_type(PurpleMedia *media, const gchar *sess_id)
 
1130
{
 
1131
#ifdef USE_VV
 
1132
        PurpleMediaSession *session;
 
1133
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), PURPLE_MEDIA_NONE);
 
1134
        session = purple_media_get_session(media, sess_id);
 
1135
        return session->type;
 
1136
#else
 
1137
        return PURPLE_MEDIA_NONE;
 
1138
#endif
 
1139
}
 
1140
/* XXX: Should wait until codecs-ready is TRUE before using this function */
 
1141
GList *
 
1142
purple_media_get_codecs(PurpleMedia *media, const gchar *sess_id)
 
1143
{
 
1144
#ifdef USE_VV
 
1145
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
1146
 
 
1147
        return purple_media_backend_get_codecs(media->priv->backend, sess_id);
 
1148
#else
 
1149
        return NULL;
 
1150
#endif
 
1151
}
 
1152
 
 
1153
GList *
 
1154
purple_media_get_local_candidates(PurpleMedia *media, const gchar *sess_id,
 
1155
                                  const gchar *participant)
 
1156
{
 
1157
#ifdef USE_VV
 
1158
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
1159
 
 
1160
        return purple_media_backend_get_local_candidates(media->priv->backend,
 
1161
                        sess_id, participant);
 
1162
#else
 
1163
        return NULL;
 
1164
#endif
 
1165
}
 
1166
 
 
1167
void
 
1168
purple_media_add_remote_candidates(PurpleMedia *media, const gchar *sess_id,
 
1169
                                   const gchar *participant,
 
1170
                                   GList *remote_candidates)
 
1171
{
 
1172
#ifdef USE_VV
 
1173
        PurpleMediaStream *stream;
 
1174
 
 
1175
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
1176
        stream = purple_media_get_stream(media, sess_id, participant);
 
1177
 
 
1178
        if (stream == NULL) {
 
1179
                purple_debug_error("media",
 
1180
                                "purple_media_add_remote_candidates: "
 
1181
                                "couldn't find stream %s %s.\n",
 
1182
                                sess_id ? sess_id : "(null)",
 
1183
                                participant ? participant : "(null)");
 
1184
                return;
 
1185
        }
 
1186
 
 
1187
        stream->remote_candidates = g_list_concat(stream->remote_candidates,
 
1188
                        purple_media_candidate_list_copy(remote_candidates));
 
1189
 
 
1190
        purple_media_backend_add_remote_candidates(media->priv->backend,
 
1191
                        sess_id, participant, remote_candidates);
 
1192
#endif
 
1193
}
 
1194
 
 
1195
GList *
 
1196
purple_media_get_active_local_candidates(PurpleMedia *media,
 
1197
                const gchar *sess_id, const gchar *participant)
 
1198
{
 
1199
#ifdef USE_VV
 
1200
        PurpleMediaStream *stream;
 
1201
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
1202
        stream = purple_media_get_stream(media, sess_id, participant);
 
1203
        return purple_media_candidate_list_copy(
 
1204
                        stream->active_local_candidates);
 
1205
#else
 
1206
        return NULL;
 
1207
#endif
 
1208
}
 
1209
 
 
1210
GList *
 
1211
purple_media_get_active_remote_candidates(PurpleMedia *media,
 
1212
                const gchar *sess_id, const gchar *participant)
 
1213
{
 
1214
#ifdef USE_VV
 
1215
        PurpleMediaStream *stream;
 
1216
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
1217
        stream = purple_media_get_stream(media, sess_id, participant);
 
1218
        return purple_media_candidate_list_copy(
 
1219
                        stream->active_remote_candidates);
 
1220
#else
 
1221
        return NULL;
 
1222
#endif
 
1223
}
 
1224
 
 
1225
gboolean
 
1226
purple_media_set_remote_codecs(PurpleMedia *media, const gchar *sess_id,
 
1227
                               const gchar *participant, GList *codecs)
 
1228
{
 
1229
#ifdef USE_VV
 
1230
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1231
 
 
1232
        return purple_media_backend_set_remote_codecs(media->priv->backend,
 
1233
                        sess_id, participant, codecs);
 
1234
#else
 
1235
        return FALSE;
 
1236
#endif
 
1237
}
 
1238
 
 
1239
gboolean
 
1240
purple_media_candidates_prepared(PurpleMedia *media,
 
1241
                const gchar *session_id, const gchar *participant)
 
1242
{
 
1243
#ifdef USE_VV
 
1244
        GList *streams;
 
1245
        gboolean prepared = TRUE;
 
1246
 
 
1247
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1248
 
 
1249
        streams = purple_media_get_streams(media, session_id, participant);
 
1250
 
 
1251
        for (; streams; streams = g_list_delete_link(streams, streams)) {
 
1252
                PurpleMediaStream *stream = streams->data;
 
1253
                if (stream->candidates_prepared == FALSE) {
 
1254
                        g_list_free(streams);
 
1255
                        prepared = FALSE;
 
1256
                        break;
 
1257
                }
 
1258
        }
 
1259
 
 
1260
        return prepared;
 
1261
#else
 
1262
        return FALSE;
 
1263
#endif
 
1264
}
 
1265
 
 
1266
gboolean
 
1267
purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, PurpleMediaCodec *codec)
 
1268
{
 
1269
#ifdef USE_VV
 
1270
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1271
 
 
1272
        return purple_media_backend_set_send_codec(
 
1273
                        media->priv->backend, sess_id, codec);
 
1274
#else
 
1275
        return FALSE;
 
1276
#endif
 
1277
}
 
1278
 
 
1279
gboolean
 
1280
purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id)
 
1281
{
 
1282
#ifdef USE_VV
 
1283
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1284
 
 
1285
        return purple_media_backend_codecs_ready(
 
1286
                        media->priv->backend, sess_id);
 
1287
#else
 
1288
        return FALSE;
 
1289
#endif
 
1290
}
 
1291
 
 
1292
gboolean
 
1293
purple_media_is_initiator(PurpleMedia *media,
 
1294
                const gchar *sess_id, const gchar *participant)
 
1295
{
 
1296
#ifdef USE_VV
 
1297
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1298
 
 
1299
        if (sess_id == NULL && participant == NULL)
 
1300
                return media->priv->initiator;
 
1301
        else if (sess_id != NULL && participant == NULL) {
 
1302
                PurpleMediaSession *session =
 
1303
                                purple_media_get_session(media, sess_id);
 
1304
                return session != NULL ? session->initiator : FALSE;
 
1305
        } else if (sess_id != NULL && participant != NULL) {
 
1306
                PurpleMediaStream *stream = purple_media_get_stream(
 
1307
                                media, sess_id, participant);
 
1308
                return stream != NULL ? stream->initiator : FALSE;
 
1309
        }
 
1310
#endif
 
1311
        return FALSE;
 
1312
}
 
1313
 
 
1314
gboolean
 
1315
purple_media_accepted(PurpleMedia *media, const gchar *sess_id,
 
1316
                const gchar *participant)
 
1317
{
 
1318
#ifdef USE_VV
 
1319
        gboolean accepted = TRUE;
 
1320
 
 
1321
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1322
 
 
1323
        if (sess_id == NULL && participant == NULL) {
 
1324
                GList *streams = media->priv->streams;
 
1325
 
 
1326
                for (; streams; streams = g_list_next(streams)) {
 
1327
                        PurpleMediaStream *stream = streams->data;
 
1328
                        if (stream->accepted == FALSE) {
 
1329
                                accepted = FALSE;
 
1330
                                break;
 
1331
                        }
 
1332
                }
 
1333
        } else if (sess_id != NULL && participant == NULL) {
 
1334
                GList *streams = purple_media_get_streams(
 
1335
                                media, sess_id, NULL);
 
1336
                for (; streams; streams =
 
1337
                                g_list_delete_link(streams, streams)) {
 
1338
                        PurpleMediaStream *stream = streams->data;
 
1339
                        if (stream->accepted == FALSE) {
 
1340
                                g_list_free(streams);
 
1341
                                accepted = FALSE;
 
1342
                                break;
 
1343
                        }
 
1344
                }
 
1345
        } else if (sess_id != NULL && participant != NULL) {
 
1346
                PurpleMediaStream *stream = purple_media_get_stream(
 
1347
                                media, sess_id, participant);
 
1348
                if (stream == NULL || stream->accepted == FALSE)
 
1349
                        accepted = FALSE;
 
1350
        }
 
1351
 
 
1352
        return accepted;
 
1353
#else
 
1354
        return FALSE;
 
1355
#endif
 
1356
}
 
1357
 
 
1358
void purple_media_set_input_volume(PurpleMedia *media,
 
1359
                const gchar *session_id, double level)
 
1360
{
 
1361
#ifdef USE_VV
 
1362
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
1363
        g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend));
 
1364
 
 
1365
        purple_media_backend_fs2_set_input_volume(
 
1366
                        PURPLE_MEDIA_BACKEND_FS2(
 
1367
                        media->priv->backend),
 
1368
                        session_id, level);
 
1369
#endif
 
1370
}
 
1371
 
 
1372
void purple_media_set_output_volume(PurpleMedia *media,
 
1373
                const gchar *session_id, const gchar *participant,
 
1374
                double level)
 
1375
{
 
1376
#ifdef USE_VV
 
1377
        g_return_if_fail(PURPLE_IS_MEDIA(media));
 
1378
        g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend));
 
1379
 
 
1380
        purple_media_backend_fs2_set_output_volume(
 
1381
                        PURPLE_MEDIA_BACKEND_FS2(
 
1382
                        media->priv->backend),
 
1383
                        session_id, participant, level);
 
1384
#endif
 
1385
}
 
1386
 
 
1387
gulong
 
1388
purple_media_set_output_window(PurpleMedia *media, const gchar *session_id,
 
1389
                const gchar *participant, gulong window_id)
 
1390
{
 
1391
#ifdef USE_VV
 
1392
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
 
1393
 
 
1394
        return purple_media_manager_set_output_window(media->priv->manager,
 
1395
                        media, session_id, participant, window_id);
 
1396
#else
 
1397
        return 0;
 
1398
#endif
 
1399
}
 
1400
 
 
1401
void
 
1402
purple_media_remove_output_windows(PurpleMedia *media)
 
1403
{
 
1404
#ifdef USE_VV
 
1405
        GList *iter = media->priv->streams;
 
1406
        for (; iter; iter = g_list_next(iter)) {
 
1407
                PurpleMediaStream *stream = iter->data;
 
1408
                purple_media_manager_remove_output_windows(
 
1409
                                media->priv->manager, media,
 
1410
                                stream->session->id, stream->participant);
 
1411
        }
 
1412
 
 
1413
        iter = purple_media_get_session_ids(media);
 
1414
        for (; iter; iter = g_list_delete_link(iter, iter)) {
 
1415
                gchar *session_name = iter->data;
 
1416
                purple_media_manager_remove_output_windows(
 
1417
                                media->priv->manager, media,
 
1418
                                session_name, NULL);
 
1419
        }
 
1420
#endif
 
1421
}
 
1422
 
 
1423
#ifdef USE_GSTREAMER
 
1424
GstElement *
 
1425
purple_media_get_tee(PurpleMedia *media,
 
1426
                const gchar *session_id, const gchar *participant)
 
1427
{
 
1428
#ifdef USE_VV
 
1429
        g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
 
1430
 
 
1431
        if (PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend))
 
1432
                return purple_media_backend_fs2_get_tee(
 
1433
                                PURPLE_MEDIA_BACKEND_FS2(
 
1434
                                media->priv->backend),
 
1435
                                session_id, participant);
 
1436
        g_return_val_if_reached(NULL);
 
1437
#else
 
1438
        return NULL;
 
1439
#endif
 
1440
}
 
1441
#endif /* USE_GSTREAMER */
 
1442