Merge lp:~ubuntu-branches/ubuntu/precise/pidgin/precise-201204042121 into lp:ubuntu/precise/pidgin

Proposed by Ubuntu Package Importer
Status: Rejected
Rejected by: James Westby
Proposed branch: lp:~ubuntu-branches/ubuntu/precise/pidgin/precise-201204042121
Merge into: lp:ubuntu/precise/pidgin
Diff against target: 1812 lines (+1779/-0) (has conflicts)
4 files modified
.pc/.quilt_patches (+1/-0)
.pc/.quilt_series (+1/-0)
.pc/70_farstream_rename.patch/libpurple/Makefile.am (+335/-0)
.pc/70_farstream_rename.patch/libpurple/media.c (+1442/-0)
Conflict adding file .pc/70_farstream_rename.patch/libpurple/Makefile.am.  Moved existing file to .pc/70_farstream_rename.patch/libpurple/Makefile.am.moved.
Conflict adding file .pc/70_farstream_rename.patch/libpurple/media.c.  Moved existing file to .pc/70_farstream_rename.patch/libpurple/media.c.moved.
To merge this branch: bzr merge lp:~ubuntu-branches/ubuntu/precise/pidgin/precise-201204042121
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+100881@code.launchpad.net

Description of the change

The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/precise/pidgin reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/precise/pidgin/precise-201204042121. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
  1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
  2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
  3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.

If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https://bugs.launchpad.net/udd linking to this merge proposal.

(this is an automatically generated message)

To post a comment you must log in.

Unmerged revisions

83. By Ken VanDine

releasing version 1:2.10.2-1ubuntu2

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.pc/.quilt_patches'
2--- .pc/.quilt_patches 1970-01-01 00:00:00 +0000
3+++ .pc/.quilt_patches 2012-04-04 21:26:20 +0000
4@@ -0,0 +1,1 @@
5+debian/patches
6
7=== added file '.pc/.quilt_series'
8--- .pc/.quilt_series 1970-01-01 00:00:00 +0000
9+++ .pc/.quilt_series 2012-04-04 21:26:20 +0000
10@@ -0,0 +1,1 @@
11+series
12
13=== added file '.pc/02_lpi.patch/.timestamp'
14=== added file '.pc/04_let_crasher_for_apport.patch/.timestamp'
15=== added file '.pc/05_default_to_irc_ubuntu_com.patch/.timestamp'
16=== added file '.pc/10_docklet_default_off.patch/.timestamp'
17=== added file '.pc/11_buddy_list_really_show.patch/.timestamp'
18=== added file '.pc/13_sounds_and_timers.patch/.timestamp'
19=== added file '.pc/60_1024x600_gtkpounce.c.patch/.timestamp'
20=== added file '.pc/60_1024x600_gtkprefs.c.patch/.timestamp'
21=== added file '.pc/70_farstream_rename.patch/.timestamp'
22=== added file '.pc/70_farstream_rename.patch/libpurple/Makefile.am'
23--- .pc/70_farstream_rename.patch/libpurple/Makefile.am 1970-01-01 00:00:00 +0000
24+++ .pc/70_farstream_rename.patch/libpurple/Makefile.am 2012-04-04 21:26:20 +0000
25@@ -0,0 +1,335 @@
26+EXTRA_DIST = \
27+ dbus-analyze-functions.py \
28+ dbus-analyze-signals.py \
29+ dbus-analyze-types.py \
30+ marshallers.list \
31+ purple-notifications-example \
32+ purple-remote \
33+ purple-send \
34+ purple-send-async \
35+ purple-url-handler \
36+ purple.h.in \
37+ purple.pc.in \
38+ purple-uninstalled.pc.in \
39+ version.h.in \
40+ Makefile.mingw \
41+ win32/global.mak \
42+ win32/libc_interface.c \
43+ win32/libc_interface.h \
44+ win32/libc_internal.h \
45+ win32/libpurplerc.rc.in \
46+ win32/rules.mak \
47+ win32/targets.mak \
48+ win32/wpurpleerror.h \
49+ win32/win32dep.c \
50+ win32/giowin32.c \
51+ win32/win32dep.h
52+
53+if USE_GCONFTOOL
54+GCONF_DIR=gconf
55+endif
56+
57+pkgconfigdir = $(libdir)/pkgconfig
58+pkgconfig_DATA = purple.pc
59+
60+SUBDIRS = $(GCONF_DIR) plugins protocols ciphers . tests example
61+
62+purple_coresources = \
63+ account.c \
64+ accountopt.c \
65+ blist.c \
66+ buddyicon.c \
67+ certificate.c \
68+ cipher.c \
69+ circbuffer.c \
70+ cmds.c \
71+ connection.c \
72+ conversation.c \
73+ core.c \
74+ debug.c \
75+ desktopitem.c \
76+ eventloop.c \
77+ ft.c \
78+ idle.c \
79+ imgstore.c \
80+ log.c \
81+ media/backend-fs2.c \
82+ media/backend-iface.c \
83+ media/candidate.c \
84+ media/codec.c \
85+ media/enum-types.c \
86+ media.c \
87+ mediamanager.c \
88+ mime.c \
89+ nat-pmp.c \
90+ network.c \
91+ ntlm.c \
92+ notify.c \
93+ plugin.c \
94+ pluginpref.c \
95+ pounce.c \
96+ prefs.c \
97+ privacy.c \
98+ proxy.c \
99+ prpl.c \
100+ request.c \
101+ roomlist.c \
102+ savedstatuses.c \
103+ server.c \
104+ signals.c \
105+ smiley.c \
106+ dnsquery.c \
107+ dnssrv.c\
108+ status.c \
109+ stringref.c \
110+ stun.c \
111+ sound.c \
112+ sound-theme.c \
113+ sound-theme-loader.c \
114+ sslconn.c \
115+ theme.c \
116+ theme-loader.c \
117+ theme-manager.c \
118+ upnp.c \
119+ util.c \
120+ value.c \
121+ version.c \
122+ xmlnode.c \
123+ whiteboard.c
124+
125+purple_builtsources = \
126+ marshallers.c
127+
128+purple_coreheaders = \
129+ account.h \
130+ accountopt.h \
131+ blist.h \
132+ buddyicon.h \
133+ certificate.h \
134+ cipher.h \
135+ circbuffer.h \
136+ cmds.h \
137+ connection.h \
138+ conversation.h \
139+ core.h \
140+ dbus-maybe.h \
141+ debug.h \
142+ desktopitem.h \
143+ eventloop.h \
144+ ft.h \
145+ gaim-compat.h \
146+ idle.h \
147+ imgstore.h \
148+ log.h \
149+ media.h \
150+ media-gst.h \
151+ mediamanager.h \
152+ mime.h \
153+ nat-pmp.h \
154+ network.h \
155+ notify.h \
156+ ntlm.h \
157+ plugin.h \
158+ pluginpref.h \
159+ pounce.h \
160+ prefs.h \
161+ privacy.h \
162+ proxy.h \
163+ prpl.h \
164+ request.h \
165+ roomlist.h \
166+ savedstatuses.h \
167+ server.h \
168+ signals.h \
169+ smiley.h \
170+ dnsquery.h \
171+ dnssrv.h \
172+ status.h \
173+ stringref.h \
174+ stun.h \
175+ sound.h \
176+ sound-theme.h \
177+ sound-theme-loader.h \
178+ sslconn.h \
179+ theme.h \
180+ theme-loader.h \
181+ theme-manager.h \
182+ upnp.h \
183+ util.h \
184+ value.h \
185+ xmlnode.h \
186+ whiteboard.h
187+
188+purple_mediaheaders = \
189+ backend-iface.h \
190+ candidate.h \
191+ codec.h \
192+ enum-types.h
193+
194+purple_builtheaders = purple.h version.h marshallers.h
195+
196+marshallers.h: marshallers.list
197+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --header > marshallers.h
198+
199+marshallers.c: marshallers.list marshallers.h
200+ $(AM_V_GEN)echo "#include \"marshallers.h\"" > marshallers.c
201+ $(AM_V_at)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --body >> marshallers.c
202+
203+if ENABLE_DBUS
204+
205+CLEANFILES = \
206+ dbus-bindings.c \
207+ dbus-client-binding.c \
208+ dbus-client-binding.h \
209+ dbus-signals.c \
210+ dbus-types.c \
211+ dbus-types.h \
212+ marshallers.c \
213+ marshallers.h \
214+ purple-client-bindings.c \
215+ purple-client-bindings.h \
216+ purple.service
217+
218+# purple dbus server
219+
220+dbus_sources = dbus-server.c dbus-useful.c
221+dbus_headers = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h
222+
223+dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h buddyicon.h \
224+ connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \
225+ savedstatuses.h smiley.h status.h server.h util.h xmlnode.h prpl.h
226+
227+purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \
228+ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) \
229+ $(purple_builtheaders)
230+dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported))
231+# We should probably make this better
232+dbus_signals = $(addprefix $(srcdir)/, $(purple_coresources)) \
233+ $(srcdir)/protocols/irc/irc.c \
234+ $(srcdir)/protocols/jabber/libxmpp.c
235+
236+dbus-types.c: dbus-analyze-types.py $(purple_build_coreheaders)
237+ $(AM_V_GEN)cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DEFINE_TYPE\(%s\) > $@
238+
239+dbus-types.h: dbus-analyze-types.py $(purple_build_coreheaders)
240+ $(AM_V_GEN)cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --pattern=PURPLE_DBUS_DECLARE_TYPE\(%s\) > $@
241+
242+dbus-bindings.c: dbus-analyze-functions.py $(dbus_exported)
243+ $(AM_V_GEN)cat $(dbus_build_exported) | $(PYTHON) $(srcdir)/dbus-analyze-functions.py > $@
244+
245+dbus-signals.c: dbus-analyze-signals.py $(dbus_signals)
246+ $(AM_V_GEN)cat $(dbus_signals) | $(PYTHON) $(srcdir)/dbus-analyze-signals.py > $@
247+
248+dbus-server.$(OBJEXT): dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
249+dbus-server.lo: dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
250+$(libpurple_la_OBJECTS): dbus-types.h
251+
252+# libpurple-client
253+
254+libpurple_client_lib = libpurple-client.la
255+
256+libpurple_client_la_SOURCES = purple-client.c purple-client.h
257+libpurple_client_la_LDFLAGS = -version-info $(PURPLE_LT_VERSION_INFO) -no-undefined
258+libpurple_client_la_LIBADD = $(DBUS_LIBS)
259+
260+purple-client-bindings.c: dbus-analyze-functions.py $(dbus_exported)
261+ $(AM_V_GEN)cat $(dbus_build_exported) | $(PYTHON) $(srcdir)/dbus-analyze-functions.py --client > $@
262+
263+purple-client-bindings.h: dbus-analyze-types.py dbus-analyze-functions.py $(purple_coreheaders) $(addprefix media/, $(purple_mediaheaders)) $(purple_builtheaders) $(dbus_exported)
264+ $(AM_V_GEN)cat $(purple_build_coreheaders) | $(PYTHON) $(srcdir)/dbus-analyze-types.py --keyword=enum --verbatim > $@
265+ $(AM_V_at)cat $(dbus_build_exported) | $(PYTHON) $(srcdir)/dbus-analyze-functions.py --client --headers >> $@
266+
267+$(libpurple_client_la_OBJECTS): purple-client-bindings.h purple-client-bindings.c
268+
269+# purple-client-example
270+
271+purple_client_example_SOURCES = purple-client-example.c
272+
273+purple_client_example_DEPENDENCIES = libpurple-client.la
274+
275+purple_client_example_LDADD = \
276+ libpurple-client.la \
277+ $(GLIB_LIBS) \
278+ $(DBUS_LIBS)
279+
280+bin_PROGRAMS = purple-client-example
281+
282+purple-client-example.$(OBJEXT): purple-client-bindings.h
283+
284+# scripts
285+
286+bin_SCRIPTS = purple-remote purple-send purple-send-async purple-url-handler
287+
288+BUILT_SOURCES = $(purple_builtheaders) \
289+ $(purple_builtsources) \
290+ dbus-bindings.c \
291+ dbus-signals.c \
292+ dbus-types.c \
293+ dbus-types.h \
294+ purple-client-bindings.c \
295+ purple-client-bindings.h
296+
297+else
298+
299+BUILT_SOURCES = $(purple_builtheaders) $(purple_builtsources)
300+
301+endif
302+
303+lib_LTLIBRARIES = libpurple.la $(libpurple_client_lib)
304+
305+libpurple_la_SOURCES = \
306+ $(purple_coresources) \
307+ $(purple_builtsources) \
308+ $(dbus_sources)
309+
310+noinst_HEADERS= \
311+ internal.h \
312+ media/backend-fs2.h \
313+ valgrind.h
314+
315+libpurpleincludedir=$(includedir)/libpurple
316+libpurpleinclude_HEADERS = \
317+ $(purple_coreheaders) \
318+ $(purple_builtheaders) \
319+ $(dbus_headers)
320+
321+mediaincludedir=$(includedir)/libpurple/media
322+mediainclude_HEADERS = \
323+ $(addprefix $(srcdir)/media/, $(purple_mediaheaders))
324+
325+libpurple_la_DEPENDENCIES = $(STATIC_LINK_LIBS)
326+libpurple_la_LDFLAGS = -export-dynamic -version-info $(PURPLE_LT_VERSION_INFO) -no-undefined
327+libpurple_la_LIBADD = \
328+ $(STATIC_LINK_LIBS) \
329+ $(DBUS_LIBS) \
330+ $(GLIB_LIBS) \
331+ $(LIBXML_LIBS) \
332+ $(NETWORKMANAGER_LIBS) \
333+ $(INTLLIBS) \
334+ $(FARSIGHT_LIBS) \
335+ $(GSTREAMER_LIBS) \
336+ $(GSTINTERFACES_LIBS) \
337+ $(IDN_LIBS) \
338+ ciphers/libpurple-ciphers.la \
339+ -lm
340+
341+AM_CPPFLAGS = \
342+ -DDATADIR=\"$(datadir)\" \
343+ -DLIBDIR=\"$(libdir)/purple-$(PURPLE_MAJOR_VERSION)/\" \
344+ -DLOCALEDIR=\"$(datadir)/locale\" \
345+ -DSYSCONFDIR=\"$(sysconfdir)\" \
346+ $(GLIB_CFLAGS) \
347+ $(DEBUG_CFLAGS) \
348+ $(DBUS_CFLAGS) \
349+ $(LIBXML_CFLAGS) \
350+ $(FARSIGHT_CFLAGS) \
351+ $(GSTREAMER_CFLAGS) \
352+ $(GSTINTERFACES_CFLAGS) \
353+ $(IDN_CFLAGS) \
354+ $(NETWORKMANAGER_CFLAGS)
355+
356+# INSTALL_SSL_CERTIFICATES is true when SSL_CERTIFICATES_DIR is empty.
357+# We want to use SSL_CERTIFICATES_DIR when it's not empty.
358+if ! INSTALL_SSL_CERTIFICATES
359+AM_CPPFLAGS += -DSSL_CERTIFICATES_DIR=\"$(SSL_CERTIFICATES_DIR)\"
360+endif
361
362=== renamed file '.pc/70_farstream_rename.patch/libpurple/Makefile.am' => '.pc/70_farstream_rename.patch/libpurple/Makefile.am.moved'
363=== added file '.pc/70_farstream_rename.patch/libpurple/media.c'
364--- .pc/70_farstream_rename.patch/libpurple/media.c 1970-01-01 00:00:00 +0000
365+++ .pc/70_farstream_rename.patch/libpurple/media.c 2012-04-04 21:26:20 +0000
366@@ -0,0 +1,1442 @@
367+/**
368+ * @file media.c Media API
369+ * @ingroup core
370+ */
371+
372+/* purple
373+ *
374+ * Purple is the legal property of its developers, whose names are too numerous
375+ * to list here. Please refer to the COPYRIGHT file distributed with this
376+ * source distribution.
377+ *
378+ * This program is free software; you can redistribute it and/or modify
379+ * it under the terms of the GNU General Public License as published by
380+ * the Free Software Foundation; either version 2 of the License, or
381+ * (at your option) any later version.
382+ *
383+ * This program is distributed in the hope that it will be useful,
384+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
385+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
386+ * GNU General Public License for more details.
387+ *
388+ * You should have received a copy of the GNU General Public License
389+ * along with this program; if not, write to the Free Software
390+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
391+ */
392+#include "internal.h"
393+
394+#include "account.h"
395+#include "media.h"
396+#include "media/backend-iface.h"
397+#include "mediamanager.h"
398+
399+#include "debug.h"
400+
401+#ifdef USE_GSTREAMER
402+#include "media/backend-fs2.h"
403+#include "marshallers.h"
404+#include "media-gst.h"
405+#endif
406+
407+#ifdef USE_VV
408+
409+/** @copydoc _PurpleMediaSession */
410+typedef struct _PurpleMediaSession PurpleMediaSession;
411+/** @copydoc _PurpleMediaStream */
412+typedef struct _PurpleMediaStream PurpleMediaStream;
413+/** @copydoc _PurpleMediaClass */
414+typedef struct _PurpleMediaClass PurpleMediaClass;
415+/** @copydoc _PurpleMediaPrivate */
416+typedef struct _PurpleMediaPrivate PurpleMediaPrivate;
417+
418+/** The media class */
419+struct _PurpleMediaClass
420+{
421+ GObjectClass parent_class; /**< The parent class. */
422+};
423+
424+/** The media class's private data */
425+struct _PurpleMedia
426+{
427+ GObject parent; /**< The parent of this object. */
428+ PurpleMediaPrivate *priv; /**< The private data of this object. */
429+};
430+
431+struct _PurpleMediaSession
432+{
433+ gchar *id;
434+ PurpleMedia *media;
435+ PurpleMediaSessionType type;
436+ gboolean initiator;
437+};
438+
439+struct _PurpleMediaStream
440+{
441+ PurpleMediaSession *session;
442+ gchar *participant;
443+
444+ GList *local_candidates;
445+ GList *remote_candidates;
446+
447+ gboolean initiator;
448+ gboolean accepted;
449+ gboolean candidates_prepared;
450+
451+ GList *active_local_candidates;
452+ GList *active_remote_candidates;
453+};
454+#endif
455+
456+struct _PurpleMediaPrivate
457+{
458+#ifdef USE_VV
459+ PurpleMediaManager *manager;
460+ PurpleAccount *account;
461+ PurpleMediaBackend *backend;
462+ gchar *conference_type;
463+ gboolean initiator;
464+ gpointer prpl_data;
465+
466+ GHashTable *sessions; /* PurpleMediaSession table */
467+ GList *participants;
468+ GList *streams; /* PurpleMediaStream table */
469+#else
470+ gpointer dummy;
471+#endif
472+};
473+
474+#ifdef USE_VV
475+#define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate))
476+
477+static void purple_media_class_init (PurpleMediaClass *klass);
478+static void purple_media_init (PurpleMedia *media);
479+static void purple_media_dispose (GObject *object);
480+static void purple_media_finalize (GObject *object);
481+static void purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
482+static void purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
483+
484+static void purple_media_new_local_candidate_cb(PurpleMediaBackend *backend,
485+ const gchar *sess_id, const gchar *participant,
486+ PurpleMediaCandidate *candidate, PurpleMedia *media);
487+static void purple_media_candidates_prepared_cb(PurpleMediaBackend *backend,
488+ const gchar *sess_id, const gchar *name, PurpleMedia *media);
489+static void purple_media_candidate_pair_established_cb(
490+ PurpleMediaBackend *backend,
491+ const gchar *sess_id, const gchar *name,
492+ PurpleMediaCandidate *local_candidate,
493+ PurpleMediaCandidate *remote_candidate,
494+ PurpleMedia *media);
495+static void purple_media_codecs_changed_cb(PurpleMediaBackend *backend,
496+ const gchar *sess_id, PurpleMedia *media);
497+
498+static GObjectClass *parent_class = NULL;
499+
500+
501+
502+enum {
503+ S_ERROR,
504+ CANDIDATES_PREPARED,
505+ CODECS_CHANGED,
506+ LEVEL,
507+ NEW_CANDIDATE,
508+ STATE_CHANGED,
509+ STREAM_INFO,
510+ LAST_SIGNAL
511+};
512+static guint purple_media_signals[LAST_SIGNAL] = {0};
513+
514+enum {
515+ PROP_0,
516+ PROP_MANAGER,
517+ PROP_BACKEND,
518+ PROP_ACCOUNT,
519+ PROP_CONFERENCE_TYPE,
520+ PROP_INITIATOR,
521+ PROP_PRPL_DATA,
522+};
523+#endif
524+
525+
526+GType
527+purple_media_get_type()
528+{
529+#ifdef USE_VV
530+ static GType type = 0;
531+
532+ if (type == 0) {
533+ static const GTypeInfo info = {
534+ sizeof(PurpleMediaClass),
535+ NULL,
536+ NULL,
537+ (GClassInitFunc) purple_media_class_init,
538+ NULL,
539+ NULL,
540+ sizeof(PurpleMedia),
541+ 0,
542+ (GInstanceInitFunc) purple_media_init,
543+ NULL
544+ };
545+ type = g_type_register_static(G_TYPE_OBJECT, "PurpleMedia", &info, 0);
546+ }
547+ return type;
548+#else
549+ return G_TYPE_NONE;
550+#endif
551+}
552+
553+#ifdef USE_VV
554+static void
555+purple_media_class_init (PurpleMediaClass *klass)
556+{
557+ GObjectClass *gobject_class = (GObjectClass*)klass;
558+ parent_class = g_type_class_peek_parent(klass);
559+
560+ gobject_class->dispose = purple_media_dispose;
561+ gobject_class->finalize = purple_media_finalize;
562+ gobject_class->set_property = purple_media_set_property;
563+ gobject_class->get_property = purple_media_get_property;
564+
565+ g_object_class_install_property(gobject_class, PROP_MANAGER,
566+ g_param_spec_object("manager",
567+ "Purple Media Manager",
568+ "The media manager that contains this media session.",
569+ PURPLE_TYPE_MEDIA_MANAGER,
570+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
571+
572+ /*
573+ * This one should be PURPLE_TYPE_MEDIA_BACKEND, but it doesn't
574+ * like interfaces because they "aren't GObjects"
575+ */
576+ g_object_class_install_property(gobject_class, PROP_BACKEND,
577+ g_param_spec_object("backend",
578+ "Purple Media Backend",
579+ "The backend object this media object uses.",
580+ G_TYPE_OBJECT,
581+ G_PARAM_READABLE));
582+
583+ g_object_class_install_property(gobject_class, PROP_ACCOUNT,
584+ g_param_spec_pointer("account",
585+ "PurpleAccount",
586+ "The account this media session is on.",
587+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
588+
589+ g_object_class_install_property(gobject_class, PROP_CONFERENCE_TYPE,
590+ g_param_spec_string("conference-type",
591+ "Conference Type",
592+ "The type of conference that this media object "
593+ "has been created to provide.",
594+ NULL,
595+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
596+
597+ g_object_class_install_property(gobject_class, PROP_INITIATOR,
598+ g_param_spec_boolean("initiator",
599+ "initiator",
600+ "If the local user initiated the conference.",
601+ FALSE,
602+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
603+
604+ g_object_class_install_property(gobject_class, PROP_PRPL_DATA,
605+ g_param_spec_pointer("prpl-data",
606+ "gpointer",
607+ "Data the prpl plugin set on the media session.",
608+ G_PARAM_READWRITE));
609+
610+ purple_media_signals[S_ERROR] = g_signal_new("error", G_TYPE_FROM_CLASS(klass),
611+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
612+ g_cclosure_marshal_VOID__STRING,
613+ G_TYPE_NONE, 1, G_TYPE_STRING);
614+ purple_media_signals[CANDIDATES_PREPARED] = g_signal_new("candidates-prepared", G_TYPE_FROM_CLASS(klass),
615+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
616+ purple_smarshal_VOID__STRING_STRING,
617+ G_TYPE_NONE, 2, G_TYPE_STRING,
618+ G_TYPE_STRING);
619+ purple_media_signals[CODECS_CHANGED] = g_signal_new("codecs-changed", G_TYPE_FROM_CLASS(klass),
620+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
621+ g_cclosure_marshal_VOID__STRING,
622+ G_TYPE_NONE, 1, G_TYPE_STRING);
623+ purple_media_signals[LEVEL] = g_signal_new("level", G_TYPE_FROM_CLASS(klass),
624+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
625+ purple_smarshal_VOID__STRING_STRING_DOUBLE,
626+ G_TYPE_NONE, 3, G_TYPE_STRING,
627+ G_TYPE_STRING, G_TYPE_DOUBLE);
628+ purple_media_signals[NEW_CANDIDATE] = g_signal_new("new-candidate", G_TYPE_FROM_CLASS(klass),
629+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
630+ purple_smarshal_VOID__POINTER_POINTER_OBJECT,
631+ G_TYPE_NONE, 3, G_TYPE_POINTER,
632+ G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE);
633+ purple_media_signals[STATE_CHANGED] = g_signal_new("state-changed", G_TYPE_FROM_CLASS(klass),
634+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
635+ purple_smarshal_VOID__ENUM_STRING_STRING,
636+ G_TYPE_NONE, 3, PURPLE_MEDIA_TYPE_STATE,
637+ G_TYPE_STRING, G_TYPE_STRING);
638+ purple_media_signals[STREAM_INFO] = g_signal_new("stream-info", G_TYPE_FROM_CLASS(klass),
639+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
640+ purple_smarshal_VOID__ENUM_STRING_STRING_BOOLEAN,
641+ G_TYPE_NONE, 4, PURPLE_MEDIA_TYPE_INFO_TYPE,
642+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
643+ g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
644+}
645+
646+
647+static void
648+purple_media_init (PurpleMedia *media)
649+{
650+ media->priv = PURPLE_MEDIA_GET_PRIVATE(media);
651+ memset(media->priv, 0, sizeof(*media->priv));
652+}
653+
654+static void
655+purple_media_stream_free(PurpleMediaStream *stream)
656+{
657+ if (stream == NULL)
658+ return;
659+
660+ g_free(stream->participant);
661+
662+ if (stream->local_candidates)
663+ purple_media_candidate_list_free(stream->local_candidates);
664+ if (stream->remote_candidates)
665+ purple_media_candidate_list_free(stream->remote_candidates);
666+
667+ if (stream->active_local_candidates)
668+ purple_media_candidate_list_free(
669+ stream->active_local_candidates);
670+ if (stream->active_remote_candidates)
671+ purple_media_candidate_list_free(
672+ stream->active_remote_candidates);
673+
674+ g_free(stream);
675+}
676+
677+static void
678+purple_media_session_free(PurpleMediaSession *session)
679+{
680+ if (session == NULL)
681+ return;
682+
683+ g_free(session->id);
684+ g_free(session);
685+}
686+
687+static void
688+purple_media_dispose(GObject *media)
689+{
690+ PurpleMediaPrivate *priv = PURPLE_MEDIA_GET_PRIVATE(media);
691+
692+ purple_debug_info("media","purple_media_dispose\n");
693+
694+ purple_media_manager_remove_media(priv->manager, PURPLE_MEDIA(media));
695+
696+ if (priv->backend) {
697+ g_object_unref(priv->backend);
698+ priv->backend = NULL;
699+ }
700+
701+ if (priv->manager) {
702+ g_object_unref(priv->manager);
703+ priv->manager = NULL;
704+ }
705+
706+ G_OBJECT_CLASS(parent_class)->dispose(media);
707+}
708+
709+static void
710+purple_media_finalize(GObject *media)
711+{
712+ PurpleMediaPrivate *priv = PURPLE_MEDIA_GET_PRIVATE(media);
713+ purple_debug_info("media","purple_media_finalize\n");
714+
715+ for (; priv->streams; priv->streams = g_list_delete_link(priv->streams, priv->streams))
716+ purple_media_stream_free(priv->streams->data);
717+
718+ for (; priv->participants; priv->participants = g_list_delete_link(
719+ priv->participants, priv->participants))
720+ g_free(priv->participants->data);
721+
722+ if (priv->sessions) {
723+ GList *sessions = g_hash_table_get_values(priv->sessions);
724+ for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
725+ purple_media_session_free(sessions->data);
726+ }
727+ g_hash_table_destroy(priv->sessions);
728+ }
729+
730+ G_OBJECT_CLASS(parent_class)->finalize(media);
731+}
732+
733+static void
734+purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
735+{
736+ PurpleMedia *media;
737+ g_return_if_fail(PURPLE_IS_MEDIA(object));
738+
739+ media = PURPLE_MEDIA(object);
740+
741+ switch (prop_id) {
742+ case PROP_MANAGER:
743+ media->priv->manager = g_value_dup_object(value);
744+ break;
745+ case PROP_ACCOUNT:
746+ media->priv->account = g_value_get_pointer(value);
747+ break;
748+ case PROP_CONFERENCE_TYPE:
749+ media->priv->conference_type =
750+ g_value_dup_string(value);
751+ media->priv->backend = g_object_new(
752+ purple_media_manager_get_backend_type(
753+ purple_media_manager_get()),
754+ "conference-type",
755+ media->priv->conference_type,
756+ "media", media,
757+ NULL);
758+ g_signal_connect(media->priv->backend,
759+ "active-candidate-pair",
760+ G_CALLBACK(
761+ purple_media_candidate_pair_established_cb),
762+ media);
763+ g_signal_connect(media->priv->backend,
764+ "candidates-prepared",
765+ G_CALLBACK(
766+ purple_media_candidates_prepared_cb),
767+ media);
768+ g_signal_connect(media->priv->backend,
769+ "codecs-changed",
770+ G_CALLBACK(
771+ purple_media_codecs_changed_cb),
772+ media);
773+ g_signal_connect(media->priv->backend,
774+ "new-candidate",
775+ G_CALLBACK(
776+ purple_media_new_local_candidate_cb),
777+ media);
778+ break;
779+ case PROP_INITIATOR:
780+ media->priv->initiator = g_value_get_boolean(value);
781+ break;
782+ case PROP_PRPL_DATA:
783+ media->priv->prpl_data = g_value_get_pointer(value);
784+ break;
785+ default:
786+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
787+ break;
788+ }
789+}
790+
791+static void
792+purple_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
793+{
794+ PurpleMedia *media;
795+ g_return_if_fail(PURPLE_IS_MEDIA(object));
796+
797+ media = PURPLE_MEDIA(object);
798+
799+ switch (prop_id) {
800+ case PROP_MANAGER:
801+ g_value_set_object(value, media->priv->manager);
802+ break;
803+ case PROP_BACKEND:
804+ g_value_set_object(value, media->priv->backend);
805+ break;
806+ case PROP_ACCOUNT:
807+ g_value_set_pointer(value, media->priv->account);
808+ break;
809+ case PROP_CONFERENCE_TYPE:
810+ g_value_set_string(value,
811+ media->priv->conference_type);
812+ break;
813+ case PROP_INITIATOR:
814+ g_value_set_boolean(value, media->priv->initiator);
815+ break;
816+ case PROP_PRPL_DATA:
817+ g_value_set_pointer(value, media->priv->prpl_data);
818+ break;
819+ default:
820+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
821+ break;
822+ }
823+
824+}
825+
826+static PurpleMediaSession*
827+purple_media_get_session(PurpleMedia *media, const gchar *sess_id)
828+{
829+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
830+ return (PurpleMediaSession*) (media->priv->sessions) ?
831+ g_hash_table_lookup(media->priv->sessions, sess_id) : NULL;
832+}
833+
834+static PurpleMediaStream*
835+purple_media_get_stream(PurpleMedia *media, const gchar *session, const gchar *participant)
836+{
837+ GList *streams;
838+
839+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
840+
841+ streams = media->priv->streams;
842+
843+ for (; streams; streams = g_list_next(streams)) {
844+ PurpleMediaStream *stream = streams->data;
845+ if (!strcmp(stream->session->id, session) &&
846+ !strcmp(stream->participant, participant))
847+ return stream;
848+ }
849+
850+ return NULL;
851+}
852+
853+static GList *
854+purple_media_get_streams(PurpleMedia *media, const gchar *session,
855+ const gchar *participant)
856+{
857+ GList *streams;
858+ GList *ret = NULL;
859+
860+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
861+
862+ streams = media->priv->streams;
863+
864+ for (; streams; streams = g_list_next(streams)) {
865+ PurpleMediaStream *stream = streams->data;
866+ if ((session == NULL ||
867+ !strcmp(stream->session->id, session)) &&
868+ (participant == NULL ||
869+ !strcmp(stream->participant, participant)))
870+ ret = g_list_append(ret, stream);
871+ }
872+
873+ return ret;
874+}
875+
876+static void
877+purple_media_add_session(PurpleMedia *media, PurpleMediaSession *session)
878+{
879+ g_return_if_fail(PURPLE_IS_MEDIA(media));
880+ g_return_if_fail(session != NULL);
881+
882+ if (!media->priv->sessions) {
883+ purple_debug_info("media", "Creating hash table for sessions\n");
884+ media->priv->sessions = g_hash_table_new_full(g_str_hash, g_str_equal,
885+ g_free, NULL);
886+ }
887+ g_hash_table_insert(media->priv->sessions, g_strdup(session->id), session);
888+}
889+
890+#if 0
891+static gboolean
892+purple_media_remove_session(PurpleMedia *media, PurpleMediaSession *session)
893+{
894+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
895+ return g_hash_table_remove(media->priv->sessions, session->id);
896+}
897+#endif
898+
899+static PurpleMediaStream *
900+purple_media_insert_stream(PurpleMediaSession *session,
901+ const gchar *name, gboolean initiator)
902+{
903+ PurpleMediaStream *media_stream;
904+
905+ g_return_val_if_fail(session != NULL, NULL);
906+
907+ media_stream = g_new0(PurpleMediaStream, 1);
908+ media_stream->participant = g_strdup(name);
909+ media_stream->session = session;
910+ media_stream->initiator = initiator;
911+
912+ session->media->priv->streams =
913+ g_list_append(session->media->priv->streams, media_stream);
914+
915+ return media_stream;
916+}
917+
918+static void
919+purple_media_insert_local_candidate(PurpleMediaSession *session, const gchar *name,
920+ PurpleMediaCandidate *candidate)
921+{
922+ PurpleMediaStream *stream;
923+
924+ g_return_if_fail(session != NULL);
925+
926+ stream = purple_media_get_stream(session->media, session->id, name);
927+ stream->local_candidates = g_list_append(stream->local_candidates, candidate);
928+}
929+#endif
930+
931+GList *
932+purple_media_get_session_ids(PurpleMedia *media)
933+{
934+#ifdef USE_VV
935+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
936+ return media->priv->sessions != NULL ?
937+ g_hash_table_get_keys(media->priv->sessions) : NULL;
938+#else
939+ return NULL;
940+#endif
941+}
942+
943+#ifdef USE_GSTREAMER
944+GstElement *
945+purple_media_get_src(PurpleMedia *media, const gchar *sess_id)
946+{
947+#ifdef USE_VV
948+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
949+
950+ if (PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend))
951+ return purple_media_backend_fs2_get_src(
952+ PURPLE_MEDIA_BACKEND_FS2(
953+ media->priv->backend), sess_id);
954+
955+ g_return_val_if_reached(NULL);
956+#else
957+ return NULL;
958+#endif
959+}
960+#endif /* USE_GSTREAMER */
961+
962+PurpleAccount *
963+purple_media_get_account(PurpleMedia *media)
964+{
965+#ifdef USE_VV
966+ PurpleAccount *account;
967+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
968+ g_object_get(G_OBJECT(media), "account", &account, NULL);
969+ return account;
970+#else
971+ return NULL;
972+#endif
973+}
974+
975+gpointer
976+purple_media_get_prpl_data(PurpleMedia *media)
977+{
978+#ifdef USE_VV
979+ gpointer prpl_data;
980+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
981+ g_object_get(G_OBJECT(media), "prpl-data", &prpl_data, NULL);
982+ return prpl_data;
983+#else
984+ return NULL;
985+#endif
986+}
987+
988+void
989+purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data)
990+{
991+#ifdef USE_VV
992+ g_return_if_fail(PURPLE_IS_MEDIA(media));
993+ g_object_set(G_OBJECT(media), "prpl-data", prpl_data, NULL);
994+#endif
995+}
996+
997+void
998+purple_media_error(PurpleMedia *media, const gchar *error, ...)
999+{
1000+#ifdef USE_VV
1001+ va_list args;
1002+ gchar *message;
1003+
1004+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1005+
1006+ va_start(args, error);
1007+ message = g_strdup_vprintf(error, args);
1008+ va_end(args);
1009+
1010+ purple_debug_error("media", "%s\n", message);
1011+ g_signal_emit(media, purple_media_signals[S_ERROR], 0, message);
1012+
1013+ g_free(message);
1014+#endif
1015+}
1016+
1017+void
1018+purple_media_end(PurpleMedia *media,
1019+ const gchar *session_id, const gchar *participant)
1020+{
1021+#ifdef USE_VV
1022+ GList *iter, *sessions = NULL, *participants = NULL;
1023+
1024+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1025+
1026+ iter = purple_media_get_streams(media, session_id, participant);
1027+
1028+ /* Free matching streams */
1029+ for (; iter; iter = g_list_delete_link(iter, iter)) {
1030+ PurpleMediaStream *stream = iter->data;
1031+
1032+ g_signal_emit(media, purple_media_signals[STATE_CHANGED],
1033+ 0, PURPLE_MEDIA_STATE_END,
1034+ stream->session->id, stream->participant);
1035+
1036+ media->priv->streams =
1037+ g_list_remove(media->priv->streams, stream);
1038+
1039+ if (g_list_find(sessions, stream->session) == NULL)
1040+ sessions = g_list_prepend(sessions, stream->session);
1041+
1042+ if (g_list_find_custom(participants, stream->participant,
1043+ (GCompareFunc)strcmp) == NULL)
1044+ participants = g_list_prepend(participants,
1045+ g_strdup(stream->participant));
1046+
1047+ purple_media_stream_free(stream);
1048+ }
1049+
1050+ iter = media->priv->streams;
1051+
1052+ /* Reduce to list of sessions to remove */
1053+ for (; iter; iter = g_list_next(iter)) {
1054+ PurpleMediaStream *stream = iter->data;
1055+
1056+ sessions = g_list_remove(sessions, stream->session);
1057+ }
1058+
1059+ /* Free sessions with no streams left */
1060+ for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
1061+ PurpleMediaSession *session = sessions->data;
1062+
1063+ g_signal_emit(media, purple_media_signals[STATE_CHANGED],
1064+ 0, PURPLE_MEDIA_STATE_END,
1065+ session->id, NULL);
1066+
1067+ g_hash_table_remove(media->priv->sessions, session->id);
1068+ purple_media_session_free(session);
1069+ }
1070+
1071+ iter = media->priv->streams;
1072+
1073+ /* Reduce to list of participants to remove */
1074+ for (; iter; iter = g_list_next(iter)) {
1075+ PurpleMediaStream *stream = iter->data;
1076+ GList *tmp;
1077+
1078+ tmp = g_list_find_custom(participants,
1079+ stream->participant, (GCompareFunc)strcmp);
1080+
1081+ if (tmp != NULL) {
1082+ g_free(tmp->data);
1083+ participants = g_list_delete_link(participants, tmp);
1084+ }
1085+ }
1086+
1087+ /* Remove participants with no streams left (just emit the signal) */
1088+ for (; participants; participants =
1089+ g_list_delete_link(participants, participants)) {
1090+ gchar *participant = participants->data;
1091+ GList *link = g_list_find_custom(media->priv->participants,
1092+ participant, (GCompareFunc)strcmp);
1093+
1094+ g_signal_emit(media, purple_media_signals[STATE_CHANGED],
1095+ 0, PURPLE_MEDIA_STATE_END,
1096+ NULL, participant);
1097+
1098+ if (link != NULL) {
1099+ g_free(link->data);
1100+ media->priv->participants = g_list_delete_link(
1101+ media->priv->participants, link);
1102+ }
1103+
1104+ g_free(participant);
1105+ }
1106+
1107+ /* Free the conference if no sessions left */
1108+ if (media->priv->sessions != NULL &&
1109+ g_hash_table_size(media->priv->sessions) == 0) {
1110+ g_signal_emit(media, purple_media_signals[STATE_CHANGED],
1111+ 0, PURPLE_MEDIA_STATE_END,
1112+ NULL, NULL);
1113+ g_object_unref(media);
1114+ return;
1115+ }
1116+#endif
1117+}
1118+
1119+void
1120+purple_media_stream_info(PurpleMedia *media, PurpleMediaInfoType type,
1121+ const gchar *session_id, const gchar *participant,
1122+ gboolean local)
1123+{
1124+#ifdef USE_VV
1125+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1126+
1127+ if (type == PURPLE_MEDIA_INFO_ACCEPT) {
1128+ GList *streams, *sessions = NULL, *participants = NULL;
1129+
1130+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1131+
1132+ streams = purple_media_get_streams(media,
1133+ session_id, participant);
1134+
1135+ /* Emit stream acceptance */
1136+ for (; streams; streams =
1137+ g_list_delete_link(streams, streams)) {
1138+ PurpleMediaStream *stream = streams->data;
1139+
1140+ stream->accepted = TRUE;
1141+
1142+ g_signal_emit(media,
1143+ purple_media_signals[STREAM_INFO],
1144+ 0, type, stream->session->id,
1145+ stream->participant, local);
1146+
1147+ if (g_list_find(sessions, stream->session) == NULL)
1148+ sessions = g_list_prepend(sessions,
1149+ stream->session);
1150+
1151+ if (g_list_find_custom(participants,
1152+ stream->participant,
1153+ (GCompareFunc)strcmp) == NULL)
1154+ participants = g_list_prepend(participants,
1155+ g_strdup(stream->participant));
1156+ }
1157+
1158+ /* Emit session acceptance */
1159+ for (; sessions; sessions =
1160+ g_list_delete_link(sessions, sessions)) {
1161+ PurpleMediaSession *session = sessions->data;
1162+
1163+ if (purple_media_accepted(media, session->id, NULL))
1164+ g_signal_emit(media, purple_media_signals[
1165+ STREAM_INFO], 0,
1166+ PURPLE_MEDIA_INFO_ACCEPT,
1167+ session->id, NULL, local);
1168+ }
1169+
1170+ /* Emit participant acceptance */
1171+ for (; participants; participants = g_list_delete_link(
1172+ participants, participants)) {
1173+ gchar *participant = participants->data;
1174+
1175+ if (purple_media_accepted(media, NULL, participant))
1176+ g_signal_emit(media, purple_media_signals[
1177+ STREAM_INFO], 0,
1178+ PURPLE_MEDIA_INFO_ACCEPT,
1179+ NULL, participant, local);
1180+
1181+ g_free(participant);
1182+ }
1183+
1184+ /* Emit conference acceptance */
1185+ if (purple_media_accepted(media, NULL, NULL))
1186+ g_signal_emit(media,
1187+ purple_media_signals[STREAM_INFO],
1188+ 0, PURPLE_MEDIA_INFO_ACCEPT,
1189+ NULL, NULL, local);
1190+
1191+ return;
1192+ } else if (type == PURPLE_MEDIA_INFO_HANGUP ||
1193+ type == PURPLE_MEDIA_INFO_REJECT) {
1194+ GList *streams;
1195+
1196+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1197+
1198+ streams = purple_media_get_streams(media,
1199+ session_id, participant);
1200+
1201+ /* Emit for stream */
1202+ for (; streams; streams =
1203+ g_list_delete_link(streams, streams)) {
1204+ PurpleMediaStream *stream = streams->data;
1205+
1206+ g_signal_emit(media,
1207+ purple_media_signals[STREAM_INFO],
1208+ 0, type, stream->session->id,
1209+ stream->participant, local);
1210+ }
1211+
1212+ if (session_id != NULL && participant != NULL) {
1213+ /* Everything that needs to be emitted has been */
1214+ } else if (session_id == NULL && participant == NULL) {
1215+ /* Emit for everything in the conference */
1216+ GList *sessions = NULL;
1217+ GList *participants = media->priv->participants;
1218+
1219+ if (media->priv->sessions != NULL)
1220+ sessions = g_hash_table_get_values(
1221+ media->priv->sessions);
1222+
1223+ /* Emit for sessions */
1224+ for (; sessions; sessions = g_list_delete_link(
1225+ sessions, sessions)) {
1226+ PurpleMediaSession *session = sessions->data;
1227+
1228+ g_signal_emit(media, purple_media_signals[
1229+ STREAM_INFO], 0, type,
1230+ session->id, NULL, local);
1231+ }
1232+
1233+ /* Emit for participants */
1234+ for (; participants; participants =
1235+ g_list_next(participants)) {
1236+ gchar *participant = participants->data;
1237+
1238+ g_signal_emit(media, purple_media_signals[
1239+ STREAM_INFO], 0, type,
1240+ NULL, participant, local);
1241+ }
1242+
1243+ /* Emit for conference */
1244+ g_signal_emit(media,
1245+ purple_media_signals[STREAM_INFO],
1246+ 0, type, NULL, NULL, local);
1247+ } else if (session_id != NULL) {
1248+ /* Emit just the specific session */
1249+ PurpleMediaSession *session =
1250+ purple_media_get_session(
1251+ media, session_id);
1252+
1253+ if (session == NULL) {
1254+ purple_debug_warning("media",
1255+ "Couldn't find session"
1256+ " to hangup/reject.\n");
1257+ } else {
1258+ g_signal_emit(media, purple_media_signals[
1259+ STREAM_INFO], 0, type,
1260+ session->id, NULL, local);
1261+ }
1262+ } else if (participant != NULL) {
1263+ /* Emit just the specific participant */
1264+ if (!g_list_find_custom(media->priv->participants,
1265+ participant, (GCompareFunc)strcmp)) {
1266+ purple_debug_warning("media",
1267+ "Couldn't find participant"
1268+ " to hangup/reject.\n");
1269+ } else {
1270+ g_signal_emit(media, purple_media_signals[
1271+ STREAM_INFO], 0, type, NULL,
1272+ participant, local);
1273+ }
1274+ }
1275+
1276+ purple_media_end(media, session_id, participant);
1277+ return;
1278+ }
1279+
1280+ g_signal_emit(media, purple_media_signals[STREAM_INFO],
1281+ 0, type, session_id, participant, local);
1282+#endif
1283+}
1284+
1285+void
1286+purple_media_set_params(PurpleMedia *media,
1287+ guint num_params, GParameter *params)
1288+{
1289+#ifdef USE_VV
1290+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1291+
1292+ purple_media_backend_set_params(media->priv->backend, num_params, params);
1293+#endif
1294+}
1295+
1296+const gchar **
1297+purple_media_get_available_params(PurpleMedia *media)
1298+{
1299+ static const gchar *NULL_ARRAY[] = { NULL };
1300+#ifdef USE_VV
1301+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL_ARRAY);
1302+
1303+ return purple_media_backend_get_available_params(media->priv->backend);
1304+#else
1305+ return NULL_ARRAY;
1306+#endif
1307+}
1308+
1309+gboolean
1310+purple_media_param_is_supported(PurpleMedia *media, const gchar *param)
1311+{
1312+#ifdef USE_VV
1313+ const gchar **params;
1314+
1315+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1316+ g_return_val_if_fail(param != NULL, FALSE);
1317+
1318+ params = purple_media_backend_get_available_params(media->priv->backend);
1319+ for (; *params != NULL; ++params)
1320+ if (!strcmp(*params, param))
1321+ return TRUE;
1322+#endif
1323+ return FALSE;
1324+}
1325+
1326+#ifdef USE_VV
1327+static void
1328+purple_media_new_local_candidate_cb(PurpleMediaBackend *backend,
1329+ const gchar *sess_id, const gchar *participant,
1330+ PurpleMediaCandidate *candidate, PurpleMedia *media)
1331+{
1332+ PurpleMediaSession *session =
1333+ purple_media_get_session(media, sess_id);
1334+
1335+ purple_media_insert_local_candidate(session, participant,
1336+ purple_media_candidate_copy(candidate));
1337+
1338+ g_signal_emit(session->media, purple_media_signals[NEW_CANDIDATE],
1339+ 0, session->id, participant, candidate);
1340+}
1341+
1342+static void
1343+purple_media_candidates_prepared_cb(PurpleMediaBackend *backend,
1344+ const gchar *sess_id, const gchar *name, PurpleMedia *media)
1345+{
1346+ PurpleMediaStream *stream_data;
1347+
1348+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1349+
1350+ stream_data = purple_media_get_stream(media, sess_id, name);
1351+ stream_data->candidates_prepared = TRUE;
1352+
1353+ g_signal_emit(media, purple_media_signals[CANDIDATES_PREPARED],
1354+ 0, sess_id, name);
1355+}
1356+
1357+/* callback called when a pair of transport candidates (local and remote)
1358+ * has been established */
1359+static void
1360+purple_media_candidate_pair_established_cb(PurpleMediaBackend *backend,
1361+ const gchar *sess_id, const gchar *name,
1362+ PurpleMediaCandidate *local_candidate,
1363+ PurpleMediaCandidate *remote_candidate,
1364+ PurpleMedia *media)
1365+{
1366+ PurpleMediaStream *stream;
1367+ GList *iter;
1368+ guint id;
1369+
1370+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1371+
1372+ stream = purple_media_get_stream(media, sess_id, name);
1373+ id = purple_media_candidate_get_component_id(local_candidate);
1374+
1375+ iter = stream->active_local_candidates;
1376+ for(; iter; iter = g_list_next(iter)) {
1377+ PurpleMediaCandidate *c = iter->data;
1378+ if (id == purple_media_candidate_get_component_id(c)) {
1379+ g_object_unref(c);
1380+ stream->active_local_candidates =
1381+ g_list_delete_link(iter, iter);
1382+ stream->active_local_candidates = g_list_prepend(
1383+ stream->active_local_candidates,
1384+ purple_media_candidate_copy(
1385+ local_candidate));
1386+ break;
1387+ }
1388+ }
1389+ if (iter == NULL)
1390+ stream->active_local_candidates = g_list_prepend(
1391+ stream->active_local_candidates,
1392+ purple_media_candidate_copy(
1393+ local_candidate));
1394+
1395+ id = purple_media_candidate_get_component_id(local_candidate);
1396+
1397+ iter = stream->active_remote_candidates;
1398+ for(; iter; iter = g_list_next(iter)) {
1399+ PurpleMediaCandidate *c = iter->data;
1400+ if (id == purple_media_candidate_get_component_id(c)) {
1401+ g_object_unref(c);
1402+ stream->active_remote_candidates =
1403+ g_list_delete_link(iter, iter);
1404+ stream->active_remote_candidates = g_list_prepend(
1405+ stream->active_remote_candidates,
1406+ purple_media_candidate_copy(
1407+ remote_candidate));
1408+ break;
1409+ }
1410+ }
1411+ if (iter == NULL)
1412+ stream->active_remote_candidates = g_list_prepend(
1413+ stream->active_remote_candidates,
1414+ purple_media_candidate_copy(
1415+ remote_candidate));
1416+
1417+ purple_debug_info("media", "candidate pair established\n");
1418+}
1419+
1420+static void
1421+purple_media_codecs_changed_cb(PurpleMediaBackend *backend,
1422+ const gchar *sess_id, PurpleMedia *media)
1423+{
1424+ g_signal_emit(media, purple_media_signals[CODECS_CHANGED], 0, sess_id);
1425+}
1426+#endif /* USE_VV */
1427+
1428+gboolean
1429+purple_media_add_stream(PurpleMedia *media, const gchar *sess_id,
1430+ const gchar *who, PurpleMediaSessionType type,
1431+ gboolean initiator, const gchar *transmitter,
1432+ guint num_params, GParameter *params)
1433+{
1434+#ifdef USE_VV
1435+ PurpleMediaSession *session;
1436+ PurpleMediaStream *stream = NULL;
1437+
1438+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1439+
1440+ if (!purple_media_backend_add_stream(media->priv->backend,
1441+ sess_id, who, type, initiator, transmitter,
1442+ num_params, params)) {
1443+ purple_debug_error("media", "Error adding stream.\n");
1444+ return FALSE;
1445+ }
1446+
1447+ session = purple_media_get_session(media, sess_id);
1448+
1449+ if (!session) {
1450+ session = g_new0(PurpleMediaSession, 1);
1451+ session->id = g_strdup(sess_id);
1452+ session->media = media;
1453+ session->type = type;
1454+ session->initiator = initiator;
1455+
1456+ purple_media_add_session(media, session);
1457+ g_signal_emit(media, purple_media_signals[STATE_CHANGED],
1458+ 0, PURPLE_MEDIA_STATE_NEW,
1459+ session->id, NULL);
1460+ }
1461+
1462+ if (!g_list_find_custom(media->priv->participants,
1463+ who, (GCompareFunc)strcmp)) {
1464+ media->priv->participants = g_list_prepend(
1465+ media->priv->participants, g_strdup(who));
1466+
1467+ g_signal_emit_by_name(media, "state-changed",
1468+ PURPLE_MEDIA_STATE_NEW, NULL, who);
1469+ }
1470+
1471+ if (purple_media_get_stream(media, sess_id, who) == NULL) {
1472+ stream = purple_media_insert_stream(session, who, initiator);
1473+
1474+ g_signal_emit(media, purple_media_signals[STATE_CHANGED],
1475+ 0, PURPLE_MEDIA_STATE_NEW,
1476+ session->id, who);
1477+ }
1478+
1479+ return TRUE;
1480+#else
1481+ return FALSE;
1482+#endif /* USE_VV */
1483+}
1484+
1485+PurpleMediaManager *
1486+purple_media_get_manager(PurpleMedia *media)
1487+{
1488+ PurpleMediaManager *ret;
1489+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
1490+ g_object_get(media, "manager", &ret, NULL);
1491+ return ret;
1492+}
1493+
1494+PurpleMediaSessionType
1495+purple_media_get_session_type(PurpleMedia *media, const gchar *sess_id)
1496+{
1497+#ifdef USE_VV
1498+ PurpleMediaSession *session;
1499+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), PURPLE_MEDIA_NONE);
1500+ session = purple_media_get_session(media, sess_id);
1501+ return session->type;
1502+#else
1503+ return PURPLE_MEDIA_NONE;
1504+#endif
1505+}
1506+/* XXX: Should wait until codecs-ready is TRUE before using this function */
1507+GList *
1508+purple_media_get_codecs(PurpleMedia *media, const gchar *sess_id)
1509+{
1510+#ifdef USE_VV
1511+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
1512+
1513+ return purple_media_backend_get_codecs(media->priv->backend, sess_id);
1514+#else
1515+ return NULL;
1516+#endif
1517+}
1518+
1519+GList *
1520+purple_media_get_local_candidates(PurpleMedia *media, const gchar *sess_id,
1521+ const gchar *participant)
1522+{
1523+#ifdef USE_VV
1524+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
1525+
1526+ return purple_media_backend_get_local_candidates(media->priv->backend,
1527+ sess_id, participant);
1528+#else
1529+ return NULL;
1530+#endif
1531+}
1532+
1533+void
1534+purple_media_add_remote_candidates(PurpleMedia *media, const gchar *sess_id,
1535+ const gchar *participant,
1536+ GList *remote_candidates)
1537+{
1538+#ifdef USE_VV
1539+ PurpleMediaStream *stream;
1540+
1541+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1542+ stream = purple_media_get_stream(media, sess_id, participant);
1543+
1544+ if (stream == NULL) {
1545+ purple_debug_error("media",
1546+ "purple_media_add_remote_candidates: "
1547+ "couldn't find stream %s %s.\n",
1548+ sess_id ? sess_id : "(null)",
1549+ participant ? participant : "(null)");
1550+ return;
1551+ }
1552+
1553+ stream->remote_candidates = g_list_concat(stream->remote_candidates,
1554+ purple_media_candidate_list_copy(remote_candidates));
1555+
1556+ purple_media_backend_add_remote_candidates(media->priv->backend,
1557+ sess_id, participant, remote_candidates);
1558+#endif
1559+}
1560+
1561+GList *
1562+purple_media_get_active_local_candidates(PurpleMedia *media,
1563+ const gchar *sess_id, const gchar *participant)
1564+{
1565+#ifdef USE_VV
1566+ PurpleMediaStream *stream;
1567+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
1568+ stream = purple_media_get_stream(media, sess_id, participant);
1569+ return purple_media_candidate_list_copy(
1570+ stream->active_local_candidates);
1571+#else
1572+ return NULL;
1573+#endif
1574+}
1575+
1576+GList *
1577+purple_media_get_active_remote_candidates(PurpleMedia *media,
1578+ const gchar *sess_id, const gchar *participant)
1579+{
1580+#ifdef USE_VV
1581+ PurpleMediaStream *stream;
1582+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
1583+ stream = purple_media_get_stream(media, sess_id, participant);
1584+ return purple_media_candidate_list_copy(
1585+ stream->active_remote_candidates);
1586+#else
1587+ return NULL;
1588+#endif
1589+}
1590+
1591+gboolean
1592+purple_media_set_remote_codecs(PurpleMedia *media, const gchar *sess_id,
1593+ const gchar *participant, GList *codecs)
1594+{
1595+#ifdef USE_VV
1596+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1597+
1598+ return purple_media_backend_set_remote_codecs(media->priv->backend,
1599+ sess_id, participant, codecs);
1600+#else
1601+ return FALSE;
1602+#endif
1603+}
1604+
1605+gboolean
1606+purple_media_candidates_prepared(PurpleMedia *media,
1607+ const gchar *session_id, const gchar *participant)
1608+{
1609+#ifdef USE_VV
1610+ GList *streams;
1611+ gboolean prepared = TRUE;
1612+
1613+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1614+
1615+ streams = purple_media_get_streams(media, session_id, participant);
1616+
1617+ for (; streams; streams = g_list_delete_link(streams, streams)) {
1618+ PurpleMediaStream *stream = streams->data;
1619+ if (stream->candidates_prepared == FALSE) {
1620+ g_list_free(streams);
1621+ prepared = FALSE;
1622+ break;
1623+ }
1624+ }
1625+
1626+ return prepared;
1627+#else
1628+ return FALSE;
1629+#endif
1630+}
1631+
1632+gboolean
1633+purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, PurpleMediaCodec *codec)
1634+{
1635+#ifdef USE_VV
1636+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1637+
1638+ return purple_media_backend_set_send_codec(
1639+ media->priv->backend, sess_id, codec);
1640+#else
1641+ return FALSE;
1642+#endif
1643+}
1644+
1645+gboolean
1646+purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id)
1647+{
1648+#ifdef USE_VV
1649+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1650+
1651+ return purple_media_backend_codecs_ready(
1652+ media->priv->backend, sess_id);
1653+#else
1654+ return FALSE;
1655+#endif
1656+}
1657+
1658+gboolean
1659+purple_media_is_initiator(PurpleMedia *media,
1660+ const gchar *sess_id, const gchar *participant)
1661+{
1662+#ifdef USE_VV
1663+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1664+
1665+ if (sess_id == NULL && participant == NULL)
1666+ return media->priv->initiator;
1667+ else if (sess_id != NULL && participant == NULL) {
1668+ PurpleMediaSession *session =
1669+ purple_media_get_session(media, sess_id);
1670+ return session != NULL ? session->initiator : FALSE;
1671+ } else if (sess_id != NULL && participant != NULL) {
1672+ PurpleMediaStream *stream = purple_media_get_stream(
1673+ media, sess_id, participant);
1674+ return stream != NULL ? stream->initiator : FALSE;
1675+ }
1676+#endif
1677+ return FALSE;
1678+}
1679+
1680+gboolean
1681+purple_media_accepted(PurpleMedia *media, const gchar *sess_id,
1682+ const gchar *participant)
1683+{
1684+#ifdef USE_VV
1685+ gboolean accepted = TRUE;
1686+
1687+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1688+
1689+ if (sess_id == NULL && participant == NULL) {
1690+ GList *streams = media->priv->streams;
1691+
1692+ for (; streams; streams = g_list_next(streams)) {
1693+ PurpleMediaStream *stream = streams->data;
1694+ if (stream->accepted == FALSE) {
1695+ accepted = FALSE;
1696+ break;
1697+ }
1698+ }
1699+ } else if (sess_id != NULL && participant == NULL) {
1700+ GList *streams = purple_media_get_streams(
1701+ media, sess_id, NULL);
1702+ for (; streams; streams =
1703+ g_list_delete_link(streams, streams)) {
1704+ PurpleMediaStream *stream = streams->data;
1705+ if (stream->accepted == FALSE) {
1706+ g_list_free(streams);
1707+ accepted = FALSE;
1708+ break;
1709+ }
1710+ }
1711+ } else if (sess_id != NULL && participant != NULL) {
1712+ PurpleMediaStream *stream = purple_media_get_stream(
1713+ media, sess_id, participant);
1714+ if (stream == NULL || stream->accepted == FALSE)
1715+ accepted = FALSE;
1716+ }
1717+
1718+ return accepted;
1719+#else
1720+ return FALSE;
1721+#endif
1722+}
1723+
1724+void purple_media_set_input_volume(PurpleMedia *media,
1725+ const gchar *session_id, double level)
1726+{
1727+#ifdef USE_VV
1728+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1729+ g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend));
1730+
1731+ purple_media_backend_fs2_set_input_volume(
1732+ PURPLE_MEDIA_BACKEND_FS2(
1733+ media->priv->backend),
1734+ session_id, level);
1735+#endif
1736+}
1737+
1738+void purple_media_set_output_volume(PurpleMedia *media,
1739+ const gchar *session_id, const gchar *participant,
1740+ double level)
1741+{
1742+#ifdef USE_VV
1743+ g_return_if_fail(PURPLE_IS_MEDIA(media));
1744+ g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend));
1745+
1746+ purple_media_backend_fs2_set_output_volume(
1747+ PURPLE_MEDIA_BACKEND_FS2(
1748+ media->priv->backend),
1749+ session_id, participant, level);
1750+#endif
1751+}
1752+
1753+gulong
1754+purple_media_set_output_window(PurpleMedia *media, const gchar *session_id,
1755+ const gchar *participant, gulong window_id)
1756+{
1757+#ifdef USE_VV
1758+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
1759+
1760+ return purple_media_manager_set_output_window(media->priv->manager,
1761+ media, session_id, participant, window_id);
1762+#else
1763+ return 0;
1764+#endif
1765+}
1766+
1767+void
1768+purple_media_remove_output_windows(PurpleMedia *media)
1769+{
1770+#ifdef USE_VV
1771+ GList *iter = media->priv->streams;
1772+ for (; iter; iter = g_list_next(iter)) {
1773+ PurpleMediaStream *stream = iter->data;
1774+ purple_media_manager_remove_output_windows(
1775+ media->priv->manager, media,
1776+ stream->session->id, stream->participant);
1777+ }
1778+
1779+ iter = purple_media_get_session_ids(media);
1780+ for (; iter; iter = g_list_delete_link(iter, iter)) {
1781+ gchar *session_name = iter->data;
1782+ purple_media_manager_remove_output_windows(
1783+ media->priv->manager, media,
1784+ session_name, NULL);
1785+ }
1786+#endif
1787+}
1788+
1789+#ifdef USE_GSTREAMER
1790+GstElement *
1791+purple_media_get_tee(PurpleMedia *media,
1792+ const gchar *session_id, const gchar *participant)
1793+{
1794+#ifdef USE_VV
1795+ g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL);
1796+
1797+ if (PURPLE_IS_MEDIA_BACKEND_FS2(media->priv->backend))
1798+ return purple_media_backend_fs2_get_tee(
1799+ PURPLE_MEDIA_BACKEND_FS2(
1800+ media->priv->backend),
1801+ session_id, participant);
1802+ g_return_val_if_reached(NULL);
1803+#else
1804+ return NULL;
1805+#endif
1806+}
1807+#endif /* USE_GSTREAMER */
1808+
1809
1810=== renamed file '.pc/70_farstream_rename.patch/libpurple/media.c' => '.pc/70_farstream_rename.patch/libpurple/media.c.moved'
1811=== added file '.pc/irc_disable_periodic_who.patch/.timestamp'
1812=== added file '.pc/libnssckbi_path.patch/.timestamp'

Subscribers

People subscribed via source and target branches

to all changes: